#include "gtb-types.h"

/*--------------------------------*\
|
|
|		INDEXING FUNCTIONS
|
|
*---------------------------------*/

#define IDX_set_empty(x) {x=0;x--;}
#define IDX_is_empty(x) (0==(1+(x)))

#define NO_KKINDEX NOINDEX
#define MAX_KKINDEX 462
#define MAX_PPINDEX 576
#define MAX_PpINDEX (24 * 48)
/*1128*/
#define MAX_AAINDEX ((63-62) + (62 * (127-62)/2) - 1 + 1)
#define MAX_AAAINDEX (64*21*31)
#define MAX_PP48_INDEX (1128)
/* (24*23*22/6) + 24 * (24*23/2) */
#define MAX_PPP48_INDEX 8648

/* VARIABLES */

static index_t			kkidx [64] [64];
static index_t			ppidx [24] [48];
static index_t 			pp48_idx[48][48];
static index_t 			ppp48_idx[48][48][48];

static sq_t				wksq [MAX_KKINDEX];
static sq_t				bksq [MAX_KKINDEX];
static sq_t				pp48_sq_x[MAX_PP48_INDEX];
static sq_t				pp48_sq_y[MAX_PP48_INDEX]; 

static index_t		 	pp_hi24 [MAX_PPINDEX]; /* was unsigned int */
static index_t		 	pp_lo48 [MAX_PPINDEX];
static unsigned int 	flipt [64] [64];
static index_t		 	aaidx [64] [64]; /* was unsigned int */
static unsigned char 	aabase [MAX_AAINDEX];

static uint8_t			ppp48_sq_x[MAX_PPP48_INDEX];
static uint8_t			ppp48_sq_y[MAX_PPP48_INDEX]; 
static uint8_t			ppp48_sq_z[MAX_PPP48_INDEX]; 

/* FUNCTIONS */

static void 	init_indexing (int verbosity);
static void 	norm_kkindex (SQUARE x, SQUARE y, /*@out@*/ SQUARE *pi, /*@out@*/ SQUARE *pj);
static void 	pp_putanchorfirst (SQUARE a, SQUARE b, /*@out@*/ SQUARE *out_anchor, /*@out@*/ SQUARE *out_loosen);

static index_t	wsq_to_pidx24 (SQUARE pawn);
static index_t 	wsq_to_pidx48 (SQUARE pawn);
static SQUARE 	pidx24_to_wsq (index_t a);
static SQUARE 	pidx48_to_wsq (index_t a);

static SQUARE 	flipWE    		(SQUARE x) { return x ^  07;}
static SQUARE 	flipNS    		(SQUARE x) { return x ^ 070;}
static SQUARE 	flipNW_SE 		(SQUARE x) { return ((x&7)<<3) | (x>>3);}
static SQUARE 	getcol    		(SQUARE x) { return x &  7;}
static SQUARE 	getrow    		(SQUARE x) { return x >> 3;}
static bool_t 	in_queenside	(sq_t x)   { return 0 == (x & (1<<2));}

/* 1:0 */
static void 	kxk_indextopc   (index_t i, SQUARE *pw, SQUARE *pb);

/* 2:0 */
static void 	kabk_indextopc  (index_t i, SQUARE *pw, SQUARE *pb);
static void 	kakb_indextopc  (index_t i, SQUARE *pw, SQUARE *pb);
static void		kaak_indextopc  (index_t i, SQUARE *pw, SQUARE *pb);

/* 2:1 */
static void 	kabkc_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
static void		kaakb_indextopc (index_t i, SQUARE *pw, SQUARE *pb);

/* 3:0 */
static void 	kabck_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
static void		kaabk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
static void		kaaak_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
static void		kabbk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);

/* one pawn */
static void 	kpk_indextopc   (index_t i, SQUARE *pw, SQUARE *pb);

/* 1:1 one pawn */
static void 	kakp_indextopc  (index_t i, SQUARE *pw, SQUARE *pb);

/* 2:0 one pawn */
static void 	kapk_indextopc  (index_t i, SQUARE *pw, SQUARE *pb);

/* 2:0 two pawns */
static void 	kppk_indextopc  (index_t i, SQUARE *pw, SQUARE *pb);

/*  2:1 one pawn */
static void		kapkb_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
static void		kabkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
static void		kaakp_indextopc (index_t i, SQUARE *pw, SQUARE *pb);

/*  2:1 + 3:0 two pawns */
static void		kppka_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
static void		kappk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
static void		kapkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb);

/*  3:0 one pawn */
static void		kabpk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
static void		kaapk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);

/*  three pawns */
static void		kpppk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
static void		kppkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb);

/* 1:1 two pawns */
static void 	kpkp_indextopc  (index_t i, SQUARE *pw, SQUARE *pb);

/* corresponding pc to index */
static bool_t 	kxk_pctoindex   (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
static bool_t 	kabk_pctoindex  (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
static bool_t 	kakb_pctoindex  (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
static bool_t 	kpk_pctoindex   (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
static bool_t 	kakp_pctoindex  (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
static bool_t 	kapk_pctoindex  (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
static bool_t   kppk_pctoindex  (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
static bool_t 	kaak_pctoindex  (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
static bool_t 	kabkc_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);

static bool_t 	kaakb_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);/**/

static bool_t 	kabck_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
static bool_t 	kaabk_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);/**/
static bool_t 	kaaak_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
static bool_t 	kabbk_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);/**/
static bool_t 	kapkb_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
static bool_t 	kabkp_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
static bool_t 	kaakp_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out);
static bool_t 	kppka_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out);
static bool_t 	kappk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out);
static bool_t 	kapkp_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out);
static bool_t 	kabpk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out);
static bool_t 	kaapk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out);
static bool_t 	kppkp_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out);
static bool_t 	kpppk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out);
static bool_t 	kpkp_pctoindex  (const SQUARE *pw,     const SQUARE *pb, /*@out@*/ index_t *out);

/* testing functions */
static bool_t 	test_kppk  (void);
static bool_t 	test_kaakb (void);
static bool_t 	test_kaabk (void);
static bool_t 	test_kaaak (void);
static bool_t 	test_kabbk (void);
static bool_t 	test_kapkb (void);
static bool_t 	test_kabkp (void);
static bool_t 	test_kppka (void);
static bool_t 	test_kappk (void);
static bool_t 	test_kapkp (void);
static bool_t 	test_kabpk (void);
static bool_t 	test_kaapk (void);
static bool_t 	test_kaakp (void);
static bool_t 	test_kppkp (void);
static bool_t 	test_kpppk (void);

static unsigned flip_type (SQUARE x, SQUARE y);
static index_t 	init_kkidx (void);
static index_t	init_ppidx (void);
static void    	init_flipt (void);
static index_t 	init_aaidx (void);
static index_t	init_aaa   (void);
static index_t	init_pp48_idx (void);
static index_t	init_ppp48_idx (void);

enum TB_INDEXES
	 {	 MAX_KXK 	= MAX_KKINDEX*64 
		,MAX_kabk 	= MAX_KKINDEX*64*64 
		,MAX_kakb 	= MAX_KKINDEX*64*64
		,MAX_kpk	= 24*64*64
		,MAX_kakp	= 24*64*64*64
		,MAX_kapk	= 24*64*64*64		
		,MAX_kppk	= MAX_PPINDEX*64*64
		,MAX_kpkp	= MAX_PpINDEX*64*64
		,MAX_kaak	= MAX_KKINDEX*MAX_AAINDEX
		,MAX_kabkc	= MAX_KKINDEX*64*64*64
		,MAX_kabck	= MAX_KKINDEX*64*64*64
		,MAX_kaakb	= MAX_KKINDEX*MAX_AAINDEX*64
		,MAX_kaabk	= MAX_KKINDEX*MAX_AAINDEX*64
		,MAX_kabbk  = MAX_KKINDEX*MAX_AAINDEX*64
		,MAX_kaaak	= MAX_KKINDEX*MAX_AAAINDEX
		,MAX_kapkb  = 24*64*64*64*64
		,MAX_kabkp  = 24*64*64*64*64
		,MAX_kabpk  = 24*64*64*64*64
		,MAX_kppka  = MAX_kppk*64
		,MAX_kappk  = MAX_kppk*64
		,MAX_kapkp  = MAX_kpkp*64
		,MAX_kaapk  = 24*MAX_AAINDEX*64*64
		,MAX_kaakp  = 24*MAX_AAINDEX*64*64
		,MAX_kppkp  = 24*MAX_PP48_INDEX*64*64
		,MAX_kpppk  = MAX_PPP48_INDEX*64*64	
};


//  Chess indexing functions
////////////////////////////////////////////////////////

static void
kxk_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	enum  {BLOCK_A = 64}; 

	index_t a = i / BLOCK_A;
	index_t b = i - a * BLOCK_A;
	
	pw[0] = wksq [a];
	pb[0] = bksq [a];
	pw[1] = (SQUARE) b;
	pw[2] = NOSQUARE;
	pb[1] = NOSQUARE;
	
	assert (kxk_pctoindex (pw, pb, &a) && a == i);

	return;
}

static bool_t 
kxk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out)
{
	enum  {BLOCK_A = 64}; 
	SQUARE *p;
	SQUARE ws[32], bs[32];
	index_t ki;
	int i;
	
	unsigned int ft;
	
	ft = flip_type (inp_pb[0],inp_pw[0]);

	assert (ft < 8);


	for (i = 0; inp_pw[i] != NOSQUARE; i++) {
		ws[i] = inp_pw[i];
	}
	ws[i] = NOSQUARE;
	for (i = 0; inp_pb[i] != NOSQUARE; i++) {
		bs[i] = inp_pb[i];
	}
	bs[i] = NOSQUARE;

	if ((ft & 1) != 0) {
		for (p = ws; *p != NOSQUARE; p++) 
				*p = flipWE (*p);
		for (p = bs; *p != NOSQUARE; p++) 
				*p = flipWE (*p);
	}

	if ((ft & 2) != 0) {
		for (p = ws; *p != NOSQUARE; p++) 
				*p = flipNS (*p);
		for (p = bs; *p != NOSQUARE; p++) 
				*p = flipNS (*p);
	}

	if ((ft & 4) != 0) {
		for (p = ws; *p != NOSQUARE; p++) 
				*p = flipNW_SE (*p);
		for (p = bs; *p != NOSQUARE; p++) 
				*p = flipNW_SE (*p);
	}

	ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */

	if (IDX_is_empty(ki)) {
		*out = NOINDEX;
		return FALSE;
	}	
	*out = ki * BLOCK_A + (index_t) ws[1]; 
	return TRUE;
	
}


static void
kabk_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	enum  {BLOCK_A = 64*64, BLOCK_B = 64}; 
	index_t a, b, c, r;

	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;
	b  = r / BLOCK_B;
	r -= b * BLOCK_B;	
	c  = r;
	
	pw[0] = wksq [a];
	pb[0] = bksq [a];

	pw[1] = (SQUARE) b;
	pw[2] = (SQUARE) c;
	pw[3] = NOSQUARE;

	pb[1] = NOSQUARE;
	
	assert (kabk_pctoindex (pw, pb, &a) && a == i);

	return;
}


static bool_t 
kabk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out)
{
	enum  {BLOCK_A = 64*64, BLOCK_B = 64}; 
	SQUARE *p;
	SQUARE ws[32], bs[32];
	index_t ki;
	int i;
	
	unsigned int ft;
	
	ft = flip_type (inp_pb[0],inp_pw[0]);

	assert (ft < 8);

	for (i = 0; inp_pw[i] != NOSQUARE; i++) {
		ws[i] = inp_pw[i];
	}
	ws[i] = NOSQUARE;
	for (i = 0; inp_pb[i] != NOSQUARE; i++) {
		bs[i] = inp_pb[i];
	}
	bs[i] = NOSQUARE;

	if ((ft & 1) != 0) {
		for (p = ws; *p != NOSQUARE; p++) 
				*p = flipWE (*p);
		for (p = bs; *p != NOSQUARE; p++) 
				*p = flipWE (*p);
	}

	if ((ft & 2) != 0) {
		for (p = ws; *p != NOSQUARE; p++) 
				*p = flipNS (*p);
		for (p = bs; *p != NOSQUARE; p++) 
				*p = flipNS (*p);
	}

	if ((ft & 4) != 0) {
		for (p = ws; *p != NOSQUARE; p++) 
				*p = flipNW_SE (*p);
		for (p = bs; *p != NOSQUARE; p++) 
				*p = flipNW_SE (*p);
	}

	ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */

	if (IDX_is_empty(ki)) {
		*out = NOINDEX;
		return FALSE;
	}	
	*out = ki * BLOCK_A + (index_t)ws[1] * BLOCK_B + (index_t)ws[2]; 
	return TRUE;
	
}


static void
kabkc_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; 
	index_t a, b, c, d, r;

	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;
	b  = r / BLOCK_B;
	r -= b * BLOCK_B;	
	c  = r / BLOCK_C;
	r -= c * BLOCK_C;
	d  = r;
	
	pw[0] = wksq [a];
	pb[0] = bksq [a];

	pw[1] = (SQUARE) b;
	pw[2] = (SQUARE) c;
	pw[3] = NOSQUARE;

	pb[1] = (SQUARE) d;
	pb[2] = NOSQUARE;
	
	assert (kabkc_pctoindex (pw, pb, &a) && a == i);

	return;
}


static bool_t 
kabkc_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out)
{
	enum  {N_WHITE = 3, N_BLACK = 2};

	enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; 
	SQUARE ws[MAX_LISTSIZE], bs[MAX_LISTSIZE];
	index_t ki;
	int i;
	unsigned int ft;

	#if 0
		ft = flip_type (inp_pb[0], inp_pw[0]);
	#else
		ft = flipt [inp_pb[0]] [inp_pw[0]];
	#endif

	assert (ft < 8);

	for (i = 0; i < N_WHITE; i++) ws[i] = inp_pw[i]; ws[N_WHITE] = NOSQUARE;
	for (i = 0; i < N_BLACK; i++) bs[i] = inp_pb[i]; bs[N_BLACK] = NOSQUARE;	

	if ((ft & WE_FLAG) != 0) {
		for (i = 0; i < N_WHITE; i++) ws[i] = flipWE (ws[i]);
		for (i = 0; i < N_BLACK; i++) bs[i] = flipWE (bs[i]);
	}

	if ((ft & NS_FLAG) != 0) {
		for (i = 0; i < N_WHITE; i++) ws[i] = flipNS (ws[i]);
		for (i = 0; i < N_BLACK; i++) bs[i] = flipNS (bs[i]);
	}

	if ((ft & NW_SE_FLAG) != 0) {
		for (i = 0; i < N_WHITE; i++) ws[i] = flipNW_SE (ws[i]);
		for (i = 0; i < N_BLACK; i++) bs[i] = flipNW_SE (bs[i]);
	}


	ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */

	if (IDX_is_empty(ki)) {
		*out = NOINDEX;
		return FALSE;
	}	
	*out = ki * BLOCK_A + (index_t)ws[1] * BLOCK_B + (index_t)ws[2] * BLOCK_C + (index_t)bs[1]; 
	return TRUE;
	
}

/* ABC/ ***/

extern void
kabck_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; 
	index_t a, b, c, d, r;

	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;
	b  = r / BLOCK_B;
	r -= b * BLOCK_B;	
	c  = r / BLOCK_C;
	r -= c * BLOCK_C;
	d  = r;
	
	pw[0] = wksq [a];
	pb[0] = bksq [a];

	pw[1] = (SQUARE) b;
	pw[2] = (SQUARE) c;
	pw[3] = (SQUARE) d;
	pw[4] = NOSQUARE;

	pb[1] = NOSQUARE;
	
	assert (kabck_pctoindex (pw, pb, &a) && a == i);

	return;
}


extern bool_t 
kabck_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out)
{
	enum  {N_WHITE = 4, N_BLACK = 1};
	enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; 

	SQUARE ws[MAX_LISTSIZE], bs[MAX_LISTSIZE];
	index_t ki;
	int i;
	unsigned int ft;

	ft = flipt [inp_pb[0]] [inp_pw[0]];

	assert (ft < 8);

	for (i = 0; i < N_WHITE; i++) ws[i] = inp_pw[i]; ws[N_WHITE] = NOSQUARE;
	for (i = 0; i < N_BLACK; i++) bs[i] = inp_pb[i]; bs[N_BLACK] = NOSQUARE;	

	if ((ft & WE_FLAG) != 0) {
		for (i = 0; i < N_WHITE; i++) ws[i] = flipWE (ws[i]);
		for (i = 0; i < N_BLACK; i++) bs[i] = flipWE (bs[i]);
	}

	if ((ft & NS_FLAG) != 0) {
		for (i = 0; i < N_WHITE; i++) ws[i] = flipNS (ws[i]);
		for (i = 0; i < N_BLACK; i++) bs[i] = flipNS (bs[i]);
	}

	if ((ft & NW_SE_FLAG) != 0) {
		for (i = 0; i < N_WHITE; i++) ws[i] = flipNW_SE (ws[i]);
		for (i = 0; i < N_BLACK; i++) bs[i] = flipNW_SE (bs[i]);
	}


	ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */

	if (IDX_is_empty(ki)) {
		*out = NOINDEX;
		return FALSE;
	}	
	*out = ki * BLOCK_A + (index_t)ws[1] * BLOCK_B + (index_t)ws[2] * BLOCK_C + (index_t)ws[3]; 
	return TRUE;
	
}


static void
kakb_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	enum  {BLOCK_A = 64*64, BLOCK_B = 64}; 
	index_t a, b, c, r;

	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;
	b  = r / BLOCK_B;
	r -= b * BLOCK_B;	
	c  = r;
	
	pw[0] = wksq [a];
	pb[0] = bksq [a];

	pw[1] = (SQUARE) b;
	pw[2] = NOSQUARE;

	pb[1] = (SQUARE) c;
	pb[2] = NOSQUARE;
	
	assert (kakb_pctoindex (pw, pb, &a) && a == i);

	return;
}


static bool_t 
kakb_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out)
{
	enum  {BLOCK_A = 64*64, BLOCK_B = 64}; 
	SQUARE ws[32], bs[32];
	index_t ki;
	unsigned int ft;
	
	#if 0
		ft = flip_type (inp_pb[0], inp_pw[0]);
	#else
		ft = flipt [inp_pb[0]] [inp_pw[0]];
	#endif

	assert (ft < 8);

	ws[0] = inp_pw[0];
	ws[1] = inp_pw[1];
	ws[2] = NOSQUARE;
	
	bs[0] = inp_pb[0];
	bs[1] = inp_pb[1];
	bs[2] = NOSQUARE;

	if ((ft & 1) != 0) {
		ws[0] = flipWE (ws[0]);
		ws[1] = flipWE (ws[1]);
		bs[0] = flipWE (bs[0]);
		bs[1] = flipWE (bs[1]);
	}

	if ((ft & 2) != 0) {
		ws[0] = flipNS (ws[0]);
		ws[1] = flipNS (ws[1]);
		bs[0] = flipNS (bs[0]);
		bs[1] = flipNS (bs[1]);
	}

	if ((ft & 4) != 0) {
		ws[0] = flipNW_SE (ws[0]);
		ws[1] = flipNW_SE (ws[1]);
		bs[0] = flipNW_SE (bs[0]);
		bs[1] = flipNW_SE (bs[1]);
	}

	ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */

	if (IDX_is_empty(ki)) {
		*out = NOINDEX;
		return FALSE;
	}	
	*out = ki * BLOCK_A + (index_t)ws[1] * BLOCK_B + (index_t)bs[1]; 
	return TRUE;
	
}

/********************** KAAKB *************************************/

static bool_t 	test_kaakb (void);
static bool_t 	kaakb_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
static void		kaakb_indextopc (index_t i, SQUARE *pw, SQUARE *pb);

static bool_t
test_kaakb (void)
{

	enum  {MAXPC = 16+1};
	char 		str[] = "kaakb";
	SQUARE 		a, b, c, d, e;
	SQUARE 		pw[MAXPC], pb[MAXPC];
	SQUARE 		px[MAXPC], py[MAXPC];	

	index_t		i, j;
	bool_t 		err = FALSE;

	printf ("%8s ", str);

	for (a = 0; a < 64; a++) {
		for (b = 0; b < 64; b++) {
		for (c = 0; c < 64; c++) {
		for (d = 0; d < 64; d++) {
		for (e = 0; e < 64; e++) {

			pw[0] = a;
			pw[1] = b;	
			pw[2] = c;
			pw[3] = NOSQUARE;
		
			pb[0] = d;
			pb[1] = e;
			pb[2] = NOSQUARE;
	
			if (kaakb_pctoindex (pw, pb, &i)) {
							kaakb_indextopc (i, px, py);		
							kaakb_pctoindex (px, py, &j);
							if (i != j) {
								err = TRUE;
							}
							assert (i == j);	
			}
	
		}
		}
		}
		}

        if ((a&1)==0) {
            printf(".");
            fflush(stdout);
        }
	}

	if (err)		
		printf ("> %s NOT passed\n", str);	
	else
		printf ("> %s PASSED\n", str);	
	return !err;
}

static void
kaakb_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	enum  {
			BLOCK_B = 64,
			BLOCK_A = BLOCK_B * MAX_AAINDEX 
		}; 
	index_t a, b, c, r, x, y;

	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;

	b  = r / BLOCK_B;
	r -= b * BLOCK_B;

	c  = r;
	
	assert (i == (a * BLOCK_A + b * BLOCK_B + c));

	pw[0] = wksq [a];
	pb[0] = bksq [a];

	x = aabase [b];
	y = (b + 1) + x - (x * (127-x)/2);

	pw[1] = (SQUARE) x;
	pw[2] = (SQUARE) y;
	pw[3] = NOSQUARE;

	pb[1] = (SQUARE) c;
	pb[2] = NOSQUARE;
	
	assert (kaakb_pctoindex (pw, pb, &a) && a == i);

	return;
}

static bool_t 
kaakb_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out)
{
	enum  {N_WHITE = 3, N_BLACK = 2};
	enum  {
			BLOCK_B = 64,
			BLOCK_A = BLOCK_B * MAX_AAINDEX 
		}; 
	SQUARE ws[MAX_LISTSIZE], bs[MAX_LISTSIZE];
	index_t ki, ai;
	unsigned int ft;
	int i;

	ft = flipt [inp_pb[0]] [inp_pw[0]];

	assert (ft < 8);

	for (i = 0; i < N_WHITE; i++) ws[i] = inp_pw[i]; ws[N_WHITE] = NOSQUARE;
	for (i = 0; i < N_BLACK; i++) bs[i] = inp_pb[i]; bs[N_BLACK] = NOSQUARE;	

	if ((ft & WE_FLAG) != 0) {
		for (i = 0; i < N_WHITE; i++) ws[i] = flipWE (ws[i]);
		for (i = 0; i < N_BLACK; i++) bs[i] = flipWE (bs[i]);
	}

	if ((ft & NS_FLAG) != 0) {
		for (i = 0; i < N_WHITE; i++) ws[i] = flipNS (ws[i]);
		for (i = 0; i < N_BLACK; i++) bs[i] = flipNS (bs[i]);
	}

	if ((ft & NW_SE_FLAG) != 0) {
		for (i = 0; i < N_WHITE; i++) ws[i] = flipNW_SE (ws[i]);
		for (i = 0; i < N_BLACK; i++) bs[i] = flipNW_SE (bs[i]);
	}

	ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */
	ai = aaidx [ws[1]] [ws[2]];

	if (IDX_is_empty(ki) || IDX_is_empty(ai)) {
		*out = NOINDEX;
		return FALSE;
	}	
	*out = ki * BLOCK_A + ai * BLOCK_B + (index_t)bs[1]; 
	return TRUE;
}

/****************** End KAAKB *************************************/

/********************** KAAB/K ************************************/

static bool_t 	test_kaabk (void);
static bool_t 	kaabk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
static void		kaabk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);

static bool_t
test_kaabk (void)
{

	enum  {MAXPC = 16+1};
	char 		str[] = "kaabk";
	SQUARE 		a, b, c, d, e;
	SQUARE 		pw[MAXPC], pb[MAXPC];
	SQUARE 		px[MAXPC], py[MAXPC];	

	index_t		i, j;
	bool_t 		err = FALSE;

	printf ("%8s ", str);

	for (a = 0; a < 64; a++) {
		for (b = 0; b < 64; b++) {
		for (c = 0; c < 64; c++) {
		for (d = 0; d < 64; d++) {
		for (e = 0; e < 64; e++) {

			pw[0] = a;
			pw[1] = b;	
			pw[2] = c;
			pw[3] = d;
			pw[4] = NOSQUARE;
		
			pb[0] = e;
			pb[1] = NOSQUARE;
	
			if (kaabk_pctoindex (pw, pb, &i)) {
							kaabk_indextopc (i, px, py);		
							kaabk_pctoindex (px, py, &j);
							if (i != j) {
								err = TRUE;
							}
							assert (i == j);	
			}
	
		}
		}
		}
		}

        if ((a&1)==0) {
            printf(".");
            fflush(stdout);
        }
	}

	if (err)		
		printf ("> %s NOT passed\n", str);	
	else
		printf ("> %s PASSED\n", str);	
	return !err;
}

static void
kaabk_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	enum  {
			BLOCK_B = 64,
			BLOCK_A = BLOCK_B * MAX_AAINDEX 
		}; 
	index_t a, b, c, r, x, y;

	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;

	b  = r / BLOCK_B;
	r -= b * BLOCK_B;

	c  = r;
	
	assert (i == (a * BLOCK_A + b * BLOCK_B + c));

	pw[0] = wksq [a];
	pb[0] = bksq [a];

	x = aabase [b];
	y = (b + 1) + x - (x * (127-x)/2);

	pw[1] = (SQUARE) x;
	pw[2] = (SQUARE) y;
	pw[3] = (SQUARE) c;
	pw[4] = NOSQUARE;

	pb[1] = NOSQUARE;
	
	assert (kaabk_pctoindex (pw, pb, &a) && a == i);

	return;
}

static bool_t 
kaabk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out)
{
	enum  {N_WHITE = 4, N_BLACK = 1};
	enum  {
			BLOCK_B = 64,
			BLOCK_A = BLOCK_B * MAX_AAINDEX 
		}; 
	SQUARE ws[MAX_LISTSIZE], bs[MAX_LISTSIZE];
	index_t ki, ai;
	unsigned int ft;
	int i;

	ft = flipt [inp_pb[0]] [inp_pw[0]];

	assert (ft < 8);

	for (i = 0; i < N_WHITE; i++) ws[i] = inp_pw[i]; ws[N_WHITE] = NOSQUARE;
	for (i = 0; i < N_BLACK; i++) bs[i] = inp_pb[i]; bs[N_BLACK] = NOSQUARE;	

	if ((ft & WE_FLAG) != 0) {
		for (i = 0; i < N_WHITE; i++) ws[i] = flipWE (ws[i]);
		for (i = 0; i < N_BLACK; i++) bs[i] = flipWE (bs[i]);
	}

	if ((ft & NS_FLAG) != 0) {
		for (i = 0; i < N_WHITE; i++) ws[i] = flipNS (ws[i]);
		for (i = 0; i < N_BLACK; i++) bs[i] = flipNS (bs[i]);
	}

	if ((ft & NW_SE_FLAG) != 0) {
		for (i = 0; i < N_WHITE; i++) ws[i] = flipNW_SE (ws[i]);
		for (i = 0; i < N_BLACK; i++) bs[i] = flipNW_SE (bs[i]);
	}

	ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */
	ai = aaidx [ws[1]] [ws[2]];

	if (IDX_is_empty(ki) || IDX_is_empty(ai)) {
		*out = NOINDEX;
		return FALSE;
	}	
	*out = ki * BLOCK_A + ai * BLOCK_B + (index_t)ws[3]; 
	return TRUE;
}

/****************** End KAAB/K *************************************/

/********************** KABB/K ************************************/

static bool_t 	test_kabbk (void);
static bool_t 	kabbk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
static void		kabbk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);

static bool_t
test_kabbk (void)
{

	enum  {MAXPC = 16+1};
	char 		str[] = "kabbk";
	SQUARE 		a, b, c, d, e;
	SQUARE 		pw[MAXPC], pb[MAXPC];
	SQUARE 		px[MAXPC], py[MAXPC];	

	index_t		i, j;
	bool_t 		err = FALSE;

	printf ("%8s ", str);

	for (a = 0; a < 64; a++) {
		for (b = 0; b < 64; b++) {
		for (c = 0; c < 64; c++) {
		for (d = 0; d < 64; d++) {
		for (e = 0; e < 64; e++) {

			pw[0] = a;
			pw[1] = b;	
			pw[2] = c;
			pw[3] = d;
			pw[4] = NOSQUARE;
		
			pb[0] = e;
			pb[1] = NOSQUARE;
	
			if (kabbk_pctoindex (pw, pb, &i)) {
							kabbk_indextopc (i, px, py);		
							kabbk_pctoindex (px, py, &j);
							if (i != j) {
								err = TRUE;
							}
							assert (i == j);	
			}
	
		}
		}
		}
		}

        if ((a&1)==0) {
            printf(".");
            fflush(stdout);
        }
	}

	if (err)		
		printf ("> %s NOT passed\n", str);	
	else
		printf ("> %s PASSED\n", str);	
	return !err;
}

static void
kabbk_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	enum  {
			BLOCK_B = 64,
			BLOCK_A = BLOCK_B * MAX_AAINDEX 
		}; 
	index_t a, b, c, r, x, y;

	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;

	b  = r / BLOCK_B;
	r -= b * BLOCK_B;

	c  = r;
	
	assert (i == (a * BLOCK_A + b * BLOCK_B + c));

	pw[0] = wksq [a];
	pb[0] = bksq [a];

	x = aabase [b];
	y = (b + 1) + x - (x * (127-x)/2);

	pw[1] = (SQUARE) c;
	pw[2] = (SQUARE) x;
	pw[3] = (SQUARE) y;
	pw[4] = NOSQUARE;

	pb[1] = NOSQUARE;
	
	assert (kabbk_pctoindex (pw, pb, &a) && a == i);

	return;
}

static bool_t 
kabbk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out)
{
	enum  {N_WHITE = 4, N_BLACK = 1};
	enum  {
			BLOCK_B = 64,
			BLOCK_A = BLOCK_B * MAX_AAINDEX 
		}; 
	SQUARE ws[MAX_LISTSIZE], bs[MAX_LISTSIZE];
	index_t ki, ai;
	unsigned int ft;
	int i;

	ft = flipt [inp_pb[0]] [inp_pw[0]];

	assert (ft < 8);

	for (i = 0; i < N_WHITE; i++) ws[i] = inp_pw[i]; ws[N_WHITE] = NOSQUARE;
	for (i = 0; i < N_BLACK; i++) bs[i] = inp_pb[i]; bs[N_BLACK] = NOSQUARE;	

	if ((ft & WE_FLAG) != 0) {
		for (i = 0; i < N_WHITE; i++) ws[i] = flipWE (ws[i]);
		for (i = 0; i < N_BLACK; i++) bs[i] = flipWE (bs[i]);
	}

	if ((ft & NS_FLAG) != 0) {
		for (i = 0; i < N_WHITE; i++) ws[i] = flipNS (ws[i]);
		for (i = 0; i < N_BLACK; i++) bs[i] = flipNS (bs[i]);
	}

	if ((ft & NW_SE_FLAG) != 0) {
		for (i = 0; i < N_WHITE; i++) ws[i] = flipNW_SE (ws[i]);
		for (i = 0; i < N_BLACK; i++) bs[i] = flipNW_SE (bs[i]);
	}

	ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */
	ai = aaidx [ws[2]] [ws[3]];

	if (IDX_is_empty(ki) || IDX_is_empty(ai)) {
		*out = NOINDEX;
		return FALSE;
	}	
	*out = ki * BLOCK_A + ai * BLOCK_B + (index_t)ws[1]; 
	return TRUE;
}

/********************** End KABB/K *************************************/

/********************** init KAAA/K ************************************/

static index_t
aaa_getsubi (sq_t x, sq_t y, sq_t z);

static sq_t 		aaa_xyz [MAX_AAAINDEX] [3];
static index_t	 	aaa_base [64];

static index_t
init_aaa (void)
/* modifies aaa_base[], aaa_xyz[][] */
{
	index_t comb [64];
	index_t accum;
	index_t a;
	
	index_t idx;
	SQUARE x, y, z;

	/* getting aaa_base */	
	comb [0] = 0;	
	for (a = 1; a < 64; a++) {
		comb [a] = a * (a-1) / 2;	
	}
	
	accum = 0;
	aaa_base [0] = accum;		
	for (a = 0; a < (64-1); a++) {
		accum += comb[a];
		aaa_base [a+1] = accum;	
	}

	assert ((accum + comb[63]) == MAX_AAAINDEX);
	/* end getting aaa_base */


	/* initialize aaa_xyz [][] */
	for (idx = 0; idx < MAX_AAAINDEX; idx++) {
		IDX_set_empty (aaa_xyz[idx][0]);
		IDX_set_empty (aaa_xyz[idx][1]);				
		IDX_set_empty (aaa_xyz[idx][2]);
	}

	idx = 0;
	for (z = 0; z < 64; z++) {
		for (y = 0; y < z; y++) {
			for (x = 0; x < y; x++) {
			
				assert (idx == aaa_getsubi (x, y, z));
	
				aaa_xyz [idx] [0] = x;
				aaa_xyz [idx] [1] = y;				
				aaa_xyz [idx] [2] = z;
				
				idx++;
			}	
		}
	}
	
	assert (idx == MAX_AAAINDEX);

	return idx;
}


static index_t
aaa_getsubi (sq_t x, sq_t y, sq_t z)
/* uses aaa_base */
{
	index_t calc_idx, base;
	
	assert (x < 64 && y < 64 && z < 64);
	assert (x < y && y < z);

	base = aaa_base[z];
	calc_idx = (index_t)x + ((index_t)y - 1) * (index_t)y / 2 + base;

	return calc_idx;
}

/********************** KAAA/K ************************************/

static bool_t 	test_kaaak (void);
static bool_t 	kaaak_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
static void		kaaak_indextopc (index_t i, SQUARE *pw, SQUARE *pb);

static bool_t
test_kaaak (void)
{

	enum  {MAXPC = 16+1};
	char 		str[] = "kaaak";
	SQUARE 		a, b, c, d, e;
	SQUARE 		pw[MAXPC], pb[MAXPC];
	SQUARE 		px[MAXPC], py[MAXPC];	

	index_t		i, j;
	bool_t 		err = FALSE;

	printf ("%8s ", str);

	for (a = 0; a < 64; a++) {
		for (b = 0; b < 64; b++) {
		for (c = 0; c < 64; c++) {
		for (d = 0; d < 64; d++) {
		for (e = 0; e < 64; e++) {

			pw[0] = a;
			pw[1] = b;	
			pw[2] = c;
			pw[3] = d;
			pw[4] = NOSQUARE;
		
			pb[0] = e;
			pb[1] = NOSQUARE;
	
			if (kaaak_pctoindex (pw, pb, &i)) {
							kaaak_indextopc (i, px, py);		
							kaaak_pctoindex (px, py, &j);
							if (i != j) {
								err = TRUE;
							}
							assert (i == j);	
			}
	
		}
		}
		}
		}

        if ((a&1)==0) {
            printf(".");
            fflush(stdout);
        }
	}

	if (err)		
		printf ("> %s NOT passed\n", str);	
	else
		printf ("> %s PASSED\n", str);	
	return !err;
}

static void
kaaak_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	enum  {
			BLOCK_A = MAX_AAAINDEX 
		};
	index_t a, b, r;

	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;

	b  = r;
	
	assert (i == (a * BLOCK_A + b));
	assert (b < BLOCK_A);

	pw[0] = wksq [a];
	pb[0] = bksq [a];

	pw[1] = aaa_xyz [b] [0];
	pw[2] = aaa_xyz [b] [1];
	pw[3] = aaa_xyz [b] [2];
	pw[4] = NOSQUARE;

	pb[1] = NOSQUARE;

	assert (kaaak_pctoindex (pw, pb, &a) && a == i);

	return;
}

static bool_t 
kaaak_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out)
{
	enum  {N_WHITE = 4, N_BLACK = 1};
	enum  {
			BLOCK_A = MAX_AAAINDEX 
		}; 
	SQUARE ws[MAX_LISTSIZE], bs[MAX_LISTSIZE];
	index_t ki, ai;
	unsigned int ft;
	int i;

	ft = flipt [inp_pb[0]] [inp_pw[0]];

	assert (ft < 8);

	for (i = 0; i < N_WHITE; i++) ws[i] = inp_pw[i]; ws[N_WHITE] = NOSQUARE;
	for (i = 0; i < N_BLACK; i++) bs[i] = inp_pb[i]; bs[N_BLACK] = NOSQUARE;	

	if ((ft & WE_FLAG) != 0) {
		for (i = 0; i < N_WHITE; i++) ws[i] = flipWE (ws[i]);
		for (i = 0; i < N_BLACK; i++) bs[i] = flipWE (bs[i]);
	}

	if ((ft & NS_FLAG) != 0) {
		for (i = 0; i < N_WHITE; i++) ws[i] = flipNS (ws[i]);
		for (i = 0; i < N_BLACK; i++) bs[i] = flipNS (bs[i]);
	}

	if ((ft & NW_SE_FLAG) != 0) {
		for (i = 0; i < N_WHITE; i++) ws[i] = flipNW_SE (ws[i]);
		for (i = 0; i < N_BLACK; i++) bs[i] = flipNW_SE (bs[i]);
	}


	{ 
		SQUARE tmp;
		if (ws[2] < ws[1]) {
            tmp = ws[1];
            ws[1] = ws[2];
            ws[2] = tmp;
		}
		if (ws[3] < ws[2]) {
            tmp = ws[2];
            ws[2] = ws[3];
            ws[3] = tmp;
		}
		if (ws[2] < ws[1]) {
            tmp = ws[1];
            ws[1] = ws[2];
            ws[2] = tmp;
		}
	}
	
	ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */

/*128 == (128 & (((ws[1]^ws[2])-1) | ((ws[1]^ws[3])-1) | ((ws[2]^ws[3])-1)) */
	
	if (ws[1] == ws[2] || ws[1] == ws[3] || ws[2] == ws[3]) {
		*out = NOINDEX;
		return FALSE;
	}
	
	ai = aaa_getsubi ( ws[1], ws[2], ws[3] );	
	
	if (IDX_is_empty(ki) || IDX_is_empty(ai)) {
		*out = NOINDEX;
		return FALSE;
	}	
	*out = ki * BLOCK_A + ai; 
	return TRUE;
}

/****************** End KAAB/K *************************************/

/**********************  KAP/KB ************************************/

static bool_t 	test_kapkb (void);
static bool_t 	kapkb_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
static void	kapkb_indextopc (index_t i, SQUARE *pw, SQUARE *pb);

static bool_t
test_kapkb (void)
{

	enum 		{MAXPC = 16+1};
	char 		str[] = "kapkb";
	SQUARE 		a, b, c, d, e;
	SQUARE 		pw[MAXPC], pb[MAXPC];
	SQUARE 		px[MAXPC], py[MAXPC];	

	index_t		i, j;
	bool_t 		err = FALSE;

	printf ("%8s ", str);

	for (a = 0; a < 64; a++) {
		for (b = 0; b < 64; b++) {
		for (c = 0; c < 64; c++) {
		for (d = 0; d < 64; d++) {
		for (e = 0; e < 64; e++) {

			if (c <= H1 || c >= A8)
				continue;
			
			pw[0] = a;
			pw[1] = b;	
			pw[2] = c;
			pw[3] = NOSQUARE;
		
			pb[0] = e;
			pb[1] = d;
			pb[2] = NOSQUARE;
	
			if (kapkb_pctoindex (pw, pb, &i)) {
							kapkb_indextopc (i, px, py);		
							kapkb_pctoindex (px, py, &j);
							if (i != j) {
								err = TRUE;
							}
							assert (i == j);	
			}
	
		}
		}
		}
		}

        if ((a&1)==0) {
            printf(".");
            fflush(stdout);
        }
	}

	if (err)		
		printf ("> %s NOT passed\n", str);	
	else
		printf ("> %s PASSED\n", str);	
	return !err;
}

static void
kapkb_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	/*---------------------------------------------------------*
		inverse work to make sure that the following is valid
		index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d * BLOCK_D + e; 
	*----------------------------------------------------------*/
	enum  {B11100  = 7u << 2};
	enum  {BLOCK_A = 64*64*64*64, BLOCK_B = 64*64*64, BLOCK_C = 64*64, BLOCK_D = 64}; 
	index_t a, b, c, d, e, r;
	index_t x;
	
	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;
	b  = r / BLOCK_B;
	r -= b * BLOCK_B;	
	c  = r / BLOCK_C;
	r -= c * BLOCK_C;	
	d  = r / BLOCK_D;
	r -= d * BLOCK_D;
	e  = r;
	
	/* x is pslice */
	x = a;
	x += x & B11100; /* get upper part and double it */
	x += 8;          /* add extra row  */
	x ^= 070;        /* flip NS */

	pw[0] = (SQUARE) b;
	pb[0] = (SQUARE) c;	
	pw[1] = (SQUARE) d;
	pw[2] = (SQUARE) x;
	pw[3] = NOSQUARE;
	pb[1] = (SQUARE) e;
	pb[2] = NOSQUARE;
	
	assert (kapkb_pctoindex (pw, pb, &a) && a == i);

	return;
}


static bool_t 
kapkb_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
{
	enum  {BLOCK_A = 64*64*64*64, BLOCK_B = 64*64*64, BLOCK_C = 64*64, BLOCK_D = 64}; 	
	index_t pslice;
	SQUARE sq;
	SQUARE pawn = pw[2];
	SQUARE wa   = pw[1];
	SQUARE wk   = pw[0];
	SQUARE bk   = pb[0];
	SQUARE ba   = pb[1];
	
	assert (A2 <= pawn && pawn < A8);

	if (  !(A2 <= pawn && pawn < A8)) {
		*out = NOINDEX;
		return FALSE;
	}	
	
	if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
		pawn = flipWE (pawn);
		wk   = flipWE (wk);		
		bk   = flipWE (bk);		
		wa   = flipWE (wa);
		ba   = flipWE (ba);		
	}

	sq = pawn;
	sq ^= 070; /* flipNS*/
	sq -= 8;   /* down one row*/
	pslice = (index_t) ((sq+(sq&3)) >> 1); 

	*out = pslice * BLOCK_A + (index_t)wk * BLOCK_B  + (index_t)bk * BLOCK_C + (index_t)wa * BLOCK_D + (index_t)ba;

	return TRUE;
}
/********************** end KAP/KB ************************************/

/*************************  KAB/KP ************************************/

static bool_t 	test_kabkp (void);
static bool_t 	kabkp_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
static void	kabkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb);

static bool_t
test_kabkp (void)
{

	enum 		{MAXPC = 16+1};
	char 		str[] = "kabkp";
	SQUARE 		a, b, c, d, e;
	SQUARE 		pw[MAXPC], pb[MAXPC];
	SQUARE 		px[MAXPC], py[MAXPC];	

	index_t		i, j;
	bool_t 		err = FALSE;

	printf ("%8s ", str);

	for (a = 0; a < 64; a++) {
		for (b = 0; b < 64; b++) {
		for (c = 0; c < 64; c++) {
		for (d = 0; d < 64; d++) {
		for (e = 0; e < 64; e++) {

			if (d <= H1 || d >= A8)
				continue;
			
			pw[0] = a;
			pw[1] = b;	
			pw[2] = c;
			pw[3] = NOSQUARE;
		
			pb[0] = e;
			pb[1] = d;
			pb[2] = NOSQUARE;
	
			if (kabkp_pctoindex (pw, pb, &i)) {
							kabkp_indextopc (i, px, py);		
							kabkp_pctoindex (px, py, &j);
							if (i != j) {
								err = TRUE;
							}
							assert (i == j);	
			}
	
		}
		}
		}
		}

        if ((a&1)==0) {
            printf(".");
            fflush(stdout);
        }
	}

	if (err)		
		printf ("> %s NOT passed\n", str);	
	else
		printf ("> %s PASSED\n", str);	
	return !err;
}

static void
kabkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	/*---------------------------------------------------------*
		inverse work to make sure that the following is valid
		index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d * BLOCK_D + e; 
	*----------------------------------------------------------*/
	enum  {B11100  = 7u << 2};
	enum  {BLOCK_A = 64*64*64*64, BLOCK_B = 64*64*64, BLOCK_C = 64*64, BLOCK_D = 64}; 
	index_t a, b, c, d, e, r;
	index_t x;
	
	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;
	b  = r / BLOCK_B;
	r -= b * BLOCK_B;	
	c  = r / BLOCK_C;
	r -= c * BLOCK_C;	
	d  = r / BLOCK_D;
	r -= d * BLOCK_D;
	e  = r;
	
	/* x is pslice */
	x = a;
	x += x & B11100; /* get upper part and double it */
	x += 8;          /* add extra row  */
	/*x ^= 070;*/        /* do not flip NS */

	pw[0] = (SQUARE) b;
	pb[0] = (SQUARE) c;	
	pw[1] = (SQUARE) d;
	pw[2] = (SQUARE) e;
	pw[3] = NOSQUARE;
	pb[1] = (SQUARE) x;
	pb[2] = NOSQUARE;
	
	assert (kabkp_pctoindex (pw, pb, &a) && a == i);

	return;
}


static bool_t 
kabkp_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
{
	enum  {BLOCK_A = 64*64*64*64, BLOCK_B = 64*64*64, BLOCK_C = 64*64, BLOCK_D = 64}; 	
	index_t pslice;
	SQUARE sq;
	SQUARE pawn = pb[1];
	SQUARE wa   = pw[1];
	SQUARE wk   = pw[0];
	SQUARE bk   = pb[0];
	SQUARE wb   = pw[2];
	
	assert (A2 <= pawn && pawn < A8);

	if (  !(A2 <= pawn && pawn < A8)) {
		*out = NOINDEX;
		return FALSE;
	}	
	
	if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
		pawn = flipWE (pawn);
		wk   = flipWE (wk);		
		bk   = flipWE (bk);		
		wa   = flipWE (wa);
		wb   = flipWE (wb);		
	}

	sq = pawn;
	/*sq ^= 070;*/ /* do not flipNS*/
	sq -= 8;   /* down one row*/
	pslice = (index_t) ((sq+(sq&3)) >> 1); 

	*out = pslice * BLOCK_A + (index_t)wk * BLOCK_B  + (index_t)bk * BLOCK_C + (index_t)wa * BLOCK_D + (index_t)wb;

	return TRUE;
}
/********************** end KAB/KP ************************************/


static void
kpk_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	/*---------------------------------------------------------*
		inverse work to make sure that the following is valid
		index = a * BLOCK_A + b * BLOCK_B + c; 
	*----------------------------------------------------------*/
	enum  {B11100  = 7u << 2};
	enum  {BLOCK_A = 64*64, BLOCK_B = 64}; 
	index_t a, b, c, r;
	index_t x;
	
	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;
	b  = r / BLOCK_B;
	r -= b * BLOCK_B;	
	c  = r;
	
	/* x is pslice */
	x = a;
	x += x & B11100; /* get upper part and double it */
	x += 8;          /* add extra row  */
	x ^= 070;        /* flip NS */
	
	pw[1] = (SQUARE) x;
	pw[0] = (SQUARE) b;
	pb[0] = (SQUARE) c;

	pw[2] = NOSQUARE;
	pb[1] = NOSQUARE;
	
	assert (kpk_pctoindex (pw, pb, &a) && a == i);

	return;
}


static bool_t 
kpk_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
{
	enum  {BLOCK_A = 64*64, BLOCK_B = 64}; 	
	index_t pslice;
	SQUARE sq;
	SQUARE pawn = pw[1];
	SQUARE wk   = pw[0];
	SQUARE bk   = pb[0];

	#ifdef DEBUG
	if (  !(A2 <= pawn && pawn < A8)) {
		SQ_CONTENT wp[MAX_LISTSIZE], bp[MAX_LISTSIZE];
        bp [0] = wp[0] = KING;
        wp[1] = PAWN;
        wp[2] = bp[1] = NOPIECE;
		output_state (0, pw, pb, wp, bp);
	}	
	#endif

	assert (A2 <= pawn && pawn < A8);

	if (  !(A2 <= pawn && pawn < A8)) {
		*out = NOINDEX;
		return FALSE;
	}	
	
	if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
		pawn = flipWE (pawn);
		wk   = flipWE (wk);		
		bk   = flipWE (bk);		
	}

	sq = pawn;
	sq ^= 070; /* flipNS*/
	sq -= 8;   /* down one row*/
	pslice = (index_t) ((sq+(sq&3)) >> 1); 

	*out = pslice * BLOCK_A + (index_t)wk * BLOCK_B  + (index_t)bk;

	return TRUE;
}


/**********************  KPP/K ************************************/

static bool_t 	test_kppk (void);
static bool_t 	kppk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
static void		kppk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);

static bool_t
test_kppk (void)
{

	enum 		{MAXPC = 16+1};
	char 		str[] = "kppk";
	SQUARE 		a, b, c, d;
	SQUARE 		pw[MAXPC], pb[MAXPC];
	SQUARE 		px[MAXPC], py[MAXPC];	

	index_t		i, j;
	bool_t 		err = FALSE;

	printf ("%8s ", str);

	for (b = 0; b < 64; b++) {
		for (c = 0; c < 64; c++) {
			sq_t anchor1, anchor2, loosen1, loosen2;
			if (c <= H1 || c >= A8)
				continue;
			if (b <= H1 || b >= A8)
				continue;

			pp_putanchorfirst (b, c, &anchor1, &loosen1);
			pp_putanchorfirst (c, b, &anchor2, &loosen2);
			if (!(anchor1 == anchor2 && loosen1 == loosen2)) {
				printf ("Output depends on input in pp_outanchorfirst()\n input:%u, %u\n",(unsigned)b,(unsigned)c);
				fatal_error();
			} 
		}
	}


	for (a = 0; a < 64; a++) {
		for (b = 0; b < 64; b++) {
		for (c = 0; c < 64; c++) {
		for (d = 0; d < 64; d++) {


			if (c <= H1 || c >= A8)
				continue;
			if (b <= H1 || b >= A8)
				continue;

			
			pw[0] = a;
			pw[1] = b;	
			pw[2] = c;
			pw[3] = NOSQUARE;
		
			pb[0] = d;
			pb[1] = NOSQUARE;
	
			if (kppk_pctoindex (pw, pb, &i)) {
							kppk_indextopc (i, px, py);		
							kppk_pctoindex (px, py, &j);
							if (i != j) {
								err = TRUE;
							}
							assert (i == j);	
			}
	
		
		}
		}
		}

        if ((a&1)==0) {
            printf(".");
            fflush(stdout);
        }
	}

	if (err)		
		printf ("> %s NOT passed\n", str);	
	else
		printf ("> %s PASSED\n", str);	
	return !err;
}

static void
kppk_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	/*---------------------------------------------------------*
		inverse work to make sure that the following is valid
		index = a * BLOCK_A + b * BLOCK_B + c; 
	*----------------------------------------------------------*/
	enum  {B11100  = 7u << 2};
	enum  {BLOCK_A = 64*64, BLOCK_B = 64}; 
	index_t a, b, c, r;
	index_t m, n;
	
	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;
	b  = r / BLOCK_B;
	r -= b * BLOCK_B;	
	c  = r;

	m = pp_hi24 [a];
	n = pp_lo48 [a];
	
	pw[0] = (SQUARE) b;
	pb[0] = (SQUARE) c;	
	pb[1] = NOSQUARE;	
	
	pw[1] = pidx24_to_wsq (m);
	pw[2] = pidx48_to_wsq (n);

	pw[3] = NOSQUARE;


	assert (A2 <= pw[1] && pw[1] < A8);
	assert (A2 <= pw[2] && pw[2] < A8);

#ifdef DEBUG
	if (!(kppk_pctoindex (pw, pb, &a) && a == i)) {
		pc_t wp[] = {KING, PAWN, PAWN, NOPIECE};
		pc_t bp[] = {KING, NOPIECE};		
		printf("Indexes not matching: input:%d, output:%d\n", i, a);
		print_pos (pw, pb, wp, bp);
	}
#endif

	assert (kppk_pctoindex (pw, pb, &a) && a == i);

	return;
}


static bool_t 
kppk_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
{
	enum  {BLOCK_A = 64*64, BLOCK_B = 64}; 	
	index_t pp_slice;
	SQUARE anchor, loosen;
	
	SQUARE wk     = pw[0];
	SQUARE pawn_a = pw[1];
	SQUARE pawn_b = pw[2];
	SQUARE bk     = pb[0];
	index_t i, j;

	#ifdef DEBUG
	if (!(A2 <= pawn_a && pawn_a < A8)) {
		printf ("\n\nsquare of pawn_a: %s\n", Square_str[pawn_a]);
		printf(" wk %s\n p1 %s\n p2 %s\n bk %s\n"
			, Square_str[wk]
			, Square_str[pawn_a]
			, Square_str[pawn_b]
			, Square_str[bk]
			);
	}
	#endif

	assert (A2 <= pawn_a && pawn_a < A8);
	assert (A2 <= pawn_b && pawn_b < A8);

	pp_putanchorfirst (pawn_a, pawn_b, &anchor, &loosen);

	if ((anchor & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
		anchor = flipWE (anchor);
		loosen = flipWE (loosen);
		wk     = flipWE (wk);		
		bk     = flipWE (bk);		
	}
 
	i = wsq_to_pidx24 (anchor);
	j = wsq_to_pidx48 (loosen);

	pp_slice = ppidx [i] [j];

	if (IDX_is_empty(pp_slice)) {
		*out = NOINDEX;
		return FALSE;
	}

	assert (pp_slice < MAX_PPINDEX );
	
	*out = pp_slice * BLOCK_A + (index_t)wk * BLOCK_B  + (index_t)bk;

	return TRUE;
}
/****************** end  KPP/K ************************************/

static void
kakp_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	/*---------------------------------------------------------*
		inverse work to make sure that the following is valid
		index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d; 
	*----------------------------------------------------------*/
	enum  {B11100  = 7u << 2};
	enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; 
	index_t a, b, c, d, r;
	index_t x;
	
	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;
	b  = r / BLOCK_B;
	r -= b * BLOCK_B;	
	c  = r / BLOCK_C;
	r -= c * BLOCK_C;	
	d  = r;
	
	/* x is pslice */
	x = a;
	x += x & B11100; /* get upper part and double it */
	x += 8;          /* add extra row  */
/*	x ^= 070;   */     /* flip NS */

	pw[0] = (SQUARE) b;
	pb[0] = (SQUARE) c;	
	pw[1] = (SQUARE) d;
	pb[1] = (SQUARE) x;
	pw[2] = NOSQUARE;
	pb[2] = NOSQUARE;
	
	assert (kakp_pctoindex (pw, pb, &a) && a == i);

	return;
}


static bool_t 
kakp_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
{
	enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; 	
	index_t pslice;
	SQUARE sq;
	SQUARE pawn = pb[1];
	SQUARE wa   = pw[1];
	SQUARE wk   = pw[0];
	SQUARE bk   = pb[0];

	assert (A2 <= pawn && pawn < A8);

	if (  !(A2 <= pawn && pawn < A8)) {
		*out = NOINDEX;
		return FALSE;
	}	
	
	if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
		pawn = flipWE (pawn);
		wk   = flipWE (wk);		
		bk   = flipWE (bk);		
		wa   = flipWE (wa);
	}

	sq = pawn;
	/*sq ^= 070;*/ /* flipNS*/
	sq -= 8;   /* down one row*/
	pslice = (index_t) ((sq+(sq&3)) >> 1); 

	*out = pslice * BLOCK_A + (index_t)wk * BLOCK_B  + (index_t)bk * BLOCK_C + (index_t)wa;

	return TRUE;
}


static void
kapk_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	/*---------------------------------------------------------*
		inverse work to make sure that the following is valid
		index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d; 
	*----------------------------------------------------------*/
	enum  {B11100  = 7u << 2};
	enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; 
	index_t a, b, c, d, r;
	index_t x;
	
	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;
	b  = r / BLOCK_B;
	r -= b * BLOCK_B;	
	c  = r / BLOCK_C;
	r -= c * BLOCK_C;	
	d  = r;
	
	/* x is pslice */
	x = a;
	x += x & B11100; /* get upper part and double it */
	x += 8;          /* add extra row  */
	x ^= 070;        /* flip NS */

	pw[0] = (SQUARE) b;
	pb[0] = (SQUARE) c;	
	pw[1] = (SQUARE) d;
	pw[2] = (SQUARE) x;
	pw[3] = NOSQUARE;
	pb[1] = NOSQUARE;
	
	assert (kapk_pctoindex (pw, pb, &a) && a == i);

	return;
}


static bool_t 
kapk_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
{
	enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; 	
	index_t pslice;
	SQUARE sq;
	SQUARE pawn = pw[2];
	SQUARE wa   = pw[1];
	SQUARE wk   = pw[0];
	SQUARE bk   = pb[0];

	assert (A2 <= pawn && pawn < A8);

	if (  !(A2 <= pawn && pawn < A8)) {
		*out = NOINDEX;
		return FALSE;
	}	
	
	if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
		pawn = flipWE (pawn);
		wk   = flipWE (wk);		
		bk   = flipWE (bk);		
		wa   = flipWE (wa);
	}

	sq = pawn;
	sq ^= 070; /* flipNS*/
	sq -= 8;   /* down one row*/
	pslice = (index_t) ((sq+(sq&3)) >> 1); 

	*out = pslice * BLOCK_A + (index_t)wk * BLOCK_B  + (index_t)bk * BLOCK_C + (index_t)wa;

	return TRUE;
}


static void
kaak_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	enum  {BLOCK_A = MAX_AAINDEX}; 
	index_t a, b, r, x, y;

	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;
	b  = r;
	
	assert (i == (a * BLOCK_A + b));

	pw[0] = wksq [a];
	pb[0] = bksq [a];

	x = aabase [b];
	y = (b + 1) + x - (x * (127-x)/2);

	pw[1] = (SQUARE) x;
	pw[2] = (SQUARE) y;
	pw[3] = NOSQUARE;

	pb[1] = NOSQUARE;
	
	assert (kaak_pctoindex (pw, pb, &a) && a == i);

	return;
}


static bool_t 
kaak_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out)
{
	enum  {N_WHITE = 3, N_BLACK = 1};
	enum  {BLOCK_A = MAX_AAINDEX}; 
	SQUARE ws[MAX_LISTSIZE], bs[MAX_LISTSIZE];
	index_t ki, ai;
	unsigned int ft;
	SQUARE i;

	ft = flipt [inp_pb[0]] [inp_pw[0]];

	assert (ft < 8);

    for (i = 0; i < N_WHITE; i++) ws[i] = inp_pw[i];
    ws[N_WHITE] = NOSQUARE;
    for (i = 0; i < N_BLACK; i++) bs[i] = inp_pb[i];
    bs[N_BLACK] = NOSQUARE;

	if ((ft & WE_FLAG) != 0) {
		for (i = 0; i < N_WHITE; i++) ws[i] = flipWE (ws[i]);
		for (i = 0; i < N_BLACK; i++) bs[i] = flipWE (bs[i]);
	}

	if ((ft & NS_FLAG) != 0) {
		for (i = 0; i < N_WHITE; i++) ws[i] = flipNS (ws[i]);
		for (i = 0; i < N_BLACK; i++) bs[i] = flipNS (bs[i]);
	}

	if ((ft & NW_SE_FLAG) != 0) {
		for (i = 0; i < N_WHITE; i++) ws[i] = flipNW_SE (ws[i]);
		for (i = 0; i < N_BLACK; i++) bs[i] = flipNW_SE (bs[i]);
	}

	ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */
	ai = (index_t) aaidx [ws[1]] [ws[2]];

	if (IDX_is_empty(ki) || IDX_is_empty(ai)) {
		*out = NOINDEX;
		return FALSE;
	}	
	*out = ki * BLOCK_A + ai; 
	return TRUE;
}

/**********************  KPP/KA ************************************/

static bool_t 	test_kppka (void);
static bool_t 	kppka_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
static void		kppka_indextopc (index_t i, SQUARE *pw, SQUARE *pb);

static bool_t
test_kppka (void)
{

	enum 		{MAXPC = 16+1};
	char 		str[] = "kppka";
	SQUARE 		a, b, c, d, e;
	SQUARE 		pw[MAXPC], pb[MAXPC];
	SQUARE 		px[MAXPC], py[MAXPC];	

	index_t		i, j;
	bool_t 		err = FALSE;

	printf ("%8s ", str);

	for (a = 0; a < 64; a++) {
		for (b = 0; b < 64; b++) {
		for (c = 0; c < 64; c++) {
		for (d = 0; d < 64; d++) {
		for (e = 0; e < 64; e++) {

			if (c <= H1 || c >= A8)
				continue;
			if (b <= H1 || b >= A8)
				continue;

			
			pw[0] = a;
			pw[1] = b;	
			pw[2] = c;
			pw[3] = NOSQUARE;
		
			pb[0] = e;
			pb[1] = d;
			pb[2] = NOSQUARE;
	
			if (kppka_pctoindex (pw, pb, &i)) {
							kppka_indextopc (i, px, py);		
							kppka_pctoindex (px, py, &j);
							if (i != j) {
								err = TRUE;
							}
							assert (i == j);	
			}
	
		}
		}
		}
		}

        if ((a&1)==0) {
            printf(".");
            fflush(stdout);
        }
	}

	if (err)		
		printf ("> %s NOT passed\n", str);	
	else
		printf ("> %s PASSED\n", str);	
	return !err;
}


static void
kppka_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	/*---------------------------------------------------------*
		inverse work to make sure that the following is valid
		index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d; 
	*----------------------------------------------------------*/

	enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; 
	index_t a, b, c, d, r;
	index_t m, n;
	
	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;
	b  = r / BLOCK_B;
	r -= b * BLOCK_B;	
	c  = r / BLOCK_C;
	r -= c * BLOCK_C;	
	d  = r;
	
	m = pp_hi24 [a];
	n = pp_lo48 [a];
	
	pw[0] = (SQUARE) b;
	pw[1] = pidx24_to_wsq (m);
	pw[2] = pidx48_to_wsq (n);
	pw[3] = NOSQUARE;

	pb[0] = (SQUARE) c;	
	pb[1] = (SQUARE) d;
	pb[2] = NOSQUARE;	


	assert (A2 <= pw[1] && pw[1] < A8);
	assert (A2 <= pw[2] && pw[2] < A8);
	assert (kppka_pctoindex (pw, pb, &a) && a == i);

	return;
}


static bool_t 
kppka_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
{
	enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; 
	index_t pp_slice;
	index_t i, j;

	SQUARE anchor, loosen;
	
	SQUARE wk     = pw[0];
	SQUARE pawn_a = pw[1];
	SQUARE pawn_b = pw[2];
	SQUARE bk     = pb[0];
	SQUARE ba	  = pb[1];	


	assert (A2 <= pawn_a && pawn_a < A8);
	assert (A2 <= pawn_b && pawn_b < A8);

	pp_putanchorfirst (pawn_a, pawn_b, &anchor, &loosen);

	if ((anchor & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
		anchor = flipWE (anchor);
		loosen = flipWE (loosen);
		wk     = flipWE (wk);		
		bk     = flipWE (bk);		
		ba	   = flipWE (ba);	
	}
 
	i = wsq_to_pidx24 (anchor);
	j = wsq_to_pidx48 (loosen);

	pp_slice = ppidx [i] [j];

	if (IDX_is_empty(pp_slice)) {
		*out = NOINDEX;
		return FALSE;
	}

	assert (pp_slice < MAX_PPINDEX );
	
	*out = pp_slice * (index_t)BLOCK_A + (index_t)wk * (index_t)BLOCK_B  + (index_t)bk * (index_t)BLOCK_C + (index_t)ba;

	return TRUE;
}

/********************** end KPP/KA ************************************/

/**********************  KAPP/K ************************************/

static bool_t 	test_kappk (void);
static bool_t 	kappk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
static void		kappk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);

static bool_t
test_kappk (void)
{

	enum 		{MAXPC = 16+1};
	char 		str[] = "kappk";
	SQUARE 		a, b, c, d, e;
	SQUARE 		pw[MAXPC], pb[MAXPC];
	SQUARE 		px[MAXPC], py[MAXPC];	

	index_t		i, j;
	bool_t 		err = FALSE;

	printf ("%8s ", str);

	for (a = 0; a < 64; a++) {
		for (b = 0; b < 64; b++) {
		for (c = 0; c < 64; c++) {
		for (d = 0; d < 64; d++) {
		for (e = 0; e < 64; e++) {

			if (c <= H1 || c >= A8)
				continue;
			if (b <= H1 || b >= A8)
				continue;

			
			pw[0] = a;
			pw[1] = d;	
			pw[2] = b;
			pw[3] = c;
			pw[4] = NOSQUARE;
		
			pb[0] = e;
			pb[1] = NOSQUARE;
	
			if (kappk_pctoindex (pw, pb, &i)) {
							kappk_indextopc (i, px, py);		
							kappk_pctoindex (px, py, &j);
							if (i != j) {
								err = TRUE;
							}
							assert (i == j);	
			}
	
		}
		}
		}
		}

        if ((a&1)==0) {
            printf(".");
            fflush(stdout);
        }
	}

	if (err)		
		printf ("> %s NOT passed\n", str);	
	else
		printf ("> %s PASSED\n", str);	
	return !err;
}


static void
kappk_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	/*---------------------------------------------------------*
		inverse work to make sure that the following is valid
		index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d; 
	*----------------------------------------------------------*/

	enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; 
	index_t a, b, c, d, r;
	index_t m, n;
	
	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;
	b  = r / BLOCK_B;
	r -= b * BLOCK_B;	
	c  = r / BLOCK_C;
	r -= c * BLOCK_C;	
	d  = r;
	
	m = pp_hi24 [a];
	n = pp_lo48 [a];
	
	pw[0] = (SQUARE) b;
	pw[1] = (SQUARE) d;
	pw[2] = pidx24_to_wsq (m);
	pw[3] = pidx48_to_wsq (n);
	pw[4] = NOSQUARE;

	pb[0] = (SQUARE) c;	
	pb[1] = NOSQUARE;	


	assert (A2 <= pw[3] && pw[3] < A8);
	assert (A2 <= pw[2] && pw[2] < A8);
	assert (kappk_pctoindex (pw, pb, &a) && a == i);

	return;
}


static bool_t 
kappk_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
{
	enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; 
	index_t pp_slice;
	SQUARE anchor, loosen;
	
	SQUARE wk     = pw[0];
	SQUARE wa	  = pw[1];	
	SQUARE pawn_a = pw[2];
	SQUARE pawn_b = pw[3];
	SQUARE bk     = pb[0];

	index_t i, j;

	assert (A2 <= pawn_a && pawn_a < A8);
	assert (A2 <= pawn_b && pawn_b < A8);

	pp_putanchorfirst (pawn_a, pawn_b, &anchor, &loosen);

	if ((anchor & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
		anchor = flipWE (anchor);
		loosen = flipWE (loosen);
		wk     = flipWE (wk);		
		bk     = flipWE (bk);		
		wa	   = flipWE (wa);	
	}
 
	i = wsq_to_pidx24 (anchor);
	j = wsq_to_pidx48 (loosen);

	pp_slice = ppidx [i] [j];

	if (IDX_is_empty(pp_slice)) {
		*out = NOINDEX;
		return FALSE;
	}

	assert (pp_slice < MAX_PPINDEX );
	
	*out = pp_slice * (index_t)BLOCK_A + (index_t)wk * (index_t)BLOCK_B  + (index_t)bk * (index_t)BLOCK_C + (index_t)wa;

	return TRUE;
}

/********************** end KAPP/K ************************************/

/**********************  KAPP/K ************************************/

static bool_t 	test_kapkp (void);
static bool_t 	kapkp_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
static void		kapkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb);

static bool_t
test_kapkp (void)
{

	enum 		{MAXPC = 16+1};
	char 		str[] = "kapkp";
	SQUARE 		a, b, c, d, e;
	SQUARE 		pw[MAXPC], pb[MAXPC];
	SQUARE 		px[MAXPC], py[MAXPC];	

	index_t		i, j;
	bool_t 		err = FALSE;

	printf ("%8s ", str);

	for (a = 0; a < 64; a++) {
		for (b = 0; b < 64; b++) {
		for (c = 0; c < 64; c++) {
		for (d = 0; d < 64; d++) {
		for (e = 0; e < 64; e++) {

			if (c <= H1 || c >= A8)
				continue;
			if (b <= H1 || b >= A8)
				continue;

			
			pw[0] = a;
			pw[1] = d;	
			pw[2] = b;
			pw[3] = NOSQUARE;
		
			pb[0] = e;
			pb[1] = c;
			pb[2] = NOSQUARE;
	
			if (kapkp_pctoindex (pw, pb, &i)) {
							kapkp_indextopc (i, px, py);		
							kapkp_pctoindex (px, py, &j);
							if (i != j) {
								err = TRUE;
							}
							assert (i == j);	
			}
	
		}
		}
		}
		}

        if ((a&1)==0) {
            printf(".");
            fflush(stdout);
        }
	}

	if (err)		
		printf ("> %s NOT passed\n", str);	
	else
		printf ("> %s PASSED\n", str);	
	return !err;
}


static bool_t 
kapkp_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
{
	enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; 	
	index_t pp_slice;
	SQUARE anchor, loosen;
	
	SQUARE wk     = pw[0];
	SQUARE wa	  = pw[1];
	SQUARE pawn_a = pw[2];
	SQUARE bk     = pb[0];
	SQUARE pawn_b = pb[1];
	index_t m, n;

	assert (A2 <= pawn_a && pawn_a < A8);
	assert (A2 <= pawn_b && pawn_b < A8);
	assert (pw[3] == NOSQUARE && pb[2] == NOSQUARE);

	anchor = pawn_a;
	loosen = pawn_b;

	if ((anchor & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
		anchor = flipWE (anchor);
		loosen = flipWE (loosen);
		wk     = flipWE (wk);		
		bk     = flipWE (bk);		
		wa	   = flipWE (wa);		
	}
 
	m = wsq_to_pidx24 (anchor);
	n = (index_t)loosen - 8;

	pp_slice = m * 48 + n; 

	if (IDX_is_empty(pp_slice)) {
		*out = NOINDEX;
		return FALSE;
	}

	assert (pp_slice < (64*MAX_PpINDEX) );
	
	*out = pp_slice * (index_t)BLOCK_A + (index_t)wk * (index_t)BLOCK_B  + (index_t)bk * (index_t)BLOCK_C + (index_t)wa;

	return TRUE;
}

static void
kapkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	/*---------------------------------------------------------*
		inverse work to make sure that the following is valid
		index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d; 
	*----------------------------------------------------------*/
	enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; 
	enum  {block_m = 48};
	index_t a, b, c, d, r;
	index_t m, n;
	SQUARE sq_m, sq_n;
	
	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;
	b  = r / BLOCK_B;
	r -= b * BLOCK_B;	
	c  = r / BLOCK_C;
	r -= c * BLOCK_C;	
	d  = r;
	
	/* unpack a, which is pslice, into m and n */
	r = a;
	m  = r / block_m;
	r -= m * block_m;
	n  = r ;

	sq_m = pidx24_to_wsq (m);
	sq_n = (SQUARE) n + 8;
	
	pw[0] = (SQUARE) b;
	pb[0] = (SQUARE) c;	
	pw[1] = (SQUARE) d;
	pw[2] = sq_m;
	pb[1] = sq_n;
	pw[3] = NOSQUARE;
	pb[2] = NOSQUARE;	
	
	assert (A2 <= sq_m && sq_m < A8);
	assert (A2 <= sq_n && sq_n < A8);
	assert (kapkp_pctoindex (pw, pb, &a) && a == i);

	return;
}

/********************** end KAP/KP ************************************/

/**********************  KABP/K ************************************/

static bool_t 	test_kabpk (void);
static bool_t 	kabpk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
static void		kabpk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);

static bool_t
test_kabpk (void)
{

	enum 		{MAXPC = 16+1};
	char 		str[] = "kabpk";
	SQUARE 		a, b, c, d, e;
	SQUARE 		pw[MAXPC], pb[MAXPC];
	SQUARE 		px[MAXPC], py[MAXPC];	

	index_t		i, j;
	bool_t 		err = FALSE;

	printf ("%8s ", str);

	for (a = 0; a < 64; a++) {
		for (b = 0; b < 64; b++) {
		for (c = 0; c < 64; c++) {
		for (d = 0; d < 64; d++) {
		for (e = 0; e < 64; e++) {

			if (d <= H1 || d >= A8)
				continue;
		
			pw[0] = a;
			pw[1] = b;	
			pw[2] = c;
			pw[3] = d;
			pw[4] = NOSQUARE;
		
			pb[0] = e;
			pb[1] = NOSQUARE;
	
			if (kabpk_pctoindex (pw, pb, &i)) {
							kabpk_indextopc (i, px, py);		
							kabpk_pctoindex (px, py, &j);
							if (i != j) {
								err = TRUE;
							}
							assert (i == j);	
			}
	
		}
		}
		}
		}

        if ((a&1)==0) {
            printf(".");
            fflush(stdout);
        }
	}

	if (err)		
		printf ("> %s NOT passed\n", str);	
	else
		printf ("> %s PASSED\n", str);	
	return !err;
}


static void
kabpk_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	
	/*---------------------------------------------------------*
		inverse work to make sure that the following is valid
		index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d * BLOCK_D + e; 
	*----------------------------------------------------------*/
	enum  {BLOCK_A = 64*64*64*64, BLOCK_B = 64*64*64, BLOCK_C = 64*64, BLOCK_D = 64}; 
	index_t a, b, c, d, e, r;
	SQUARE x;
	
	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;
	b  = r / BLOCK_B;
	r -= b * BLOCK_B;	
	c  = r / BLOCK_C;
	r -= c * BLOCK_C;	
	d  = r / BLOCK_D;
	r -= d * BLOCK_D;
	e  = r;
	
	x = pidx24_to_wsq(a);

	pw[0] = (SQUARE) b;
	pw[1] = (SQUARE) d;
	pw[2] = (SQUARE) e;
	pw[3] = x;
	pw[4] = NOSQUARE;

	pb[0] = (SQUARE) c;	
	pb[1] = NOSQUARE;
	
	assert (kabpk_pctoindex (pw, pb, &a) && a == i);

	return;
}


static bool_t 
kabpk_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
{
	enum  {BLOCK_A = 64*64*64*64, BLOCK_B = 64*64*64, BLOCK_C = 64*64, BLOCK_D = 64}; 	
	index_t pslice;

	SQUARE wk   = pw[0];
	SQUARE wa   = pw[1];
	SQUARE wb   = pw[2];
	SQUARE pawn = pw[3];
	SQUARE bk   = pb[0];

	assert (A2 <= pawn && pawn < A8);
	
	if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
		pawn = flipWE (pawn);
		wk   = flipWE (wk);		
		bk   = flipWE (bk);		
		wa   = flipWE (wa);
		wb   = flipWE (wb);		
	}

	pslice = wsq_to_pidx24 (pawn);

	*out = pslice * (index_t)BLOCK_A + (index_t)wk * (index_t)BLOCK_B  + (index_t)bk * (index_t)BLOCK_C + (index_t)wa * (index_t)BLOCK_D + (index_t)wb;

	return TRUE;
}

/********************** end KABP/K ************************************/

/**********************  KAAP/K ************************************/

static bool_t 	test_kaapk (void);
static bool_t 	kaapk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
static void		kaapk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);

static bool_t
test_kaapk (void)
{

	enum 		{MAXPC = 16+1};
	char 		str[] = "kaapk";
	SQUARE 		a, b, c, d, e;
	SQUARE 		pw[MAXPC], pb[MAXPC];
	SQUARE 		px[MAXPC], py[MAXPC];	

	index_t		i, j;
	bool_t 		err = FALSE;

	printf ("%8s ", str);

	for (a = 0; a < 64; a++) {
		for (b = 0; b < 64; b++) {
		for (c = 0; c < 64; c++) {
		for (d = 0; d < 64; d++) {
		for (e = 0; e < 64; e++) {

			if (d <= H1 || d >= A8)
				continue;
		
			pw[0] = a;
			pw[1] = b;	
			pw[2] = c;
			pw[3] = d;
			pw[4] = NOSQUARE;
		
			pb[0] = e;
			pb[1] = NOSQUARE;
	
			if (kaapk_pctoindex (pw, pb, &i)) {
							kaapk_indextopc (i, px, py);		
							kaapk_pctoindex (px, py, &j);
							if (i != j) {
								err = TRUE;
							}
							assert (i == j);	
			}
	
		}
		}
		}
		}

        if ((a&1)==0) {
            printf(".");
            fflush(stdout);
        }
	}

	if (err)		
		printf ("> %s NOT passed\n", str);	
	else
		printf ("> %s PASSED\n", str);	
	return !err;
}


static void
kaapk_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	/*---------------------------------------------------------*
		inverse work to make sure that the following is valid
		index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d; 
	*----------------------------------------------------------*/
	enum 	{BLOCK_C = MAX_AAINDEX
			,BLOCK_B = 64*BLOCK_C
			,BLOCK_A = 64*BLOCK_B
	}; 	
	index_t a, b, c, d, r;
	index_t x, y, z;
	
	assert (i >= 0);

	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;
	b  = r / BLOCK_B;
	r -= b * BLOCK_B;	
	c  = r / BLOCK_C;
	r -= c * BLOCK_C;	
	d  = r;

	z = (index_t) pidx24_to_wsq(a);
	
	/* split d into x, y*/
	x = aabase [d];
	y = (d + 1) + x - (x * (127-x)/2);

	assert (aaidx[x][y] == aaidx[y][x]);
	assert (aaidx[x][y] == d);


	pw[0] = (SQUARE) b;
	pw[1] = (SQUARE) x;
	pw[2] = (SQUARE) y;
	pw[3] = (SQUARE) z;
	pw[4] = NOSQUARE;
	
	pb[0] = (SQUARE) c;	
	pb[1] = NOSQUARE;
	
	assert (kaapk_pctoindex (pw, pb, &a) && a == i);

	return;
}


static bool_t 
kaapk_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
{
	enum 	{BLOCK_C = MAX_AAINDEX
			,BLOCK_B = 64*BLOCK_C
			,BLOCK_A = 64*BLOCK_B
	}; 	
	index_t aa_combo, pslice;

	SQUARE wk   = pw[0];
	SQUARE wa   = pw[1];
	SQUARE wa2  = pw[2];
	SQUARE pawn = pw[3];
	SQUARE bk   = pb[0];

	assert (A2 <= pawn && pawn < A8);

	if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
		pawn = flipWE (pawn);
		wk   = flipWE (wk);		
		bk   = flipWE (bk);		
		wa   = flipWE (wa);
		wa2  = flipWE (wa2);
	}

	pslice = wsq_to_pidx24 (pawn);

	aa_combo = (index_t) aaidx [wa] [wa2];

	if (IDX_is_empty(aa_combo)) {
		*out = NOINDEX;
		return FALSE;
	}	

	*out = pslice * (index_t)BLOCK_A + (index_t)wk * (index_t)BLOCK_B  + (index_t)bk * (index_t)BLOCK_C + aa_combo;

	assert (*out >= 0);

	return TRUE;
}

/********************** end KAAP/K ************************************/

/**********************  KAA/KP ************************************/

static bool_t 	test_kaakp (void);
static bool_t 	kaakp_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
static void		kaakp_indextopc (index_t i, SQUARE *pw, SQUARE *pb);

static bool_t
test_kaakp (void)
{

	enum 		{MAXPC = 16+1};
	char 		str[] = "kaakp";
	SQUARE 		a, b, c, d, e;
	SQUARE 		pw[MAXPC], pb[MAXPC];
	SQUARE 		px[MAXPC], py[MAXPC];	

	index_t		i, j;
	bool_t 		err = FALSE;

	printf ("%8s ", str);

	for (a = 0; a < 64; a++) {
		for (b = 0; b < 64; b++) {
		for (c = 0; c < 64; c++) {
		for (d = 0; d < 64; d++) {
		for (e = 0; e < 64; e++) {

			if (d <= H1 || d >= A8)
				continue;
		
			pw[0] = a;
			pw[1] = b;	
			pw[2] = c;
			pw[3] = NOSQUARE;
		
			pb[0] = e;
			pb[1] = d;
			pb[2] = NOSQUARE;
	
			if (kaakp_pctoindex (pw, pb, &i)) {
							kaakp_indextopc (i, px, py);		
							kaakp_pctoindex (px, py, &j);
							if (i != j) {
								err = TRUE;
							}
							assert (i == j);	
			}
	
		}
		}
		}
		}

        if ((a&1)==0) {
            printf(".");
            fflush(stdout);
        }
	}

	if (err)		
		printf ("> %s NOT passed\n", str);	
	else
		printf ("> %s PASSED\n", str);	
	return !err;
}


static void
kaakp_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	/*---------------------------------------------------------*
		inverse work to make sure that the following is valid
		index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d; 
	*----------------------------------------------------------*/
	enum 	{BLOCK_C = MAX_AAINDEX
			,BLOCK_B = 64*BLOCK_C
			,BLOCK_A = 64*BLOCK_B
	}; 	
	index_t a, b, c, d, r;
	index_t x, y, z;
	SQUARE zq;	

	assert (i >= 0);

	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;
	b  = r / BLOCK_B;
	r -= b * BLOCK_B;	
	c  = r / BLOCK_C;
	r -= c * BLOCK_C;	
	d  = r;

	zq = pidx24_to_wsq(a); 
	z  = (index_t)flipNS(zq);

	
	/* split d into x, y*/
	x = aabase [d];
	y = (d + 1) + x - (x * (127-x)/2);

	assert (aaidx[x][y] == aaidx[y][x]);
	assert (aaidx[x][y] == d);


	pw[0] = (SQUARE)b;
	pw[1] = (SQUARE)x;
	pw[2] = (SQUARE)y;
	pw[3] = NOSQUARE;
	
	pb[0] = (SQUARE)c;	
	pb[1] = (SQUARE)z;
	pb[2] = NOSQUARE;
	
	assert (kaakp_pctoindex (pw, pb, &a) && a == i);

	return;
}


static bool_t 
kaakp_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
{
	enum 	{BLOCK_C = MAX_AAINDEX
			,BLOCK_B = 64*BLOCK_C
			,BLOCK_A = 64*BLOCK_B
	}; 	
	index_t aa_combo, pslice;

	SQUARE wk   = pw[0];
	SQUARE wa   = pw[1];
	SQUARE wa2  = pw[2];
	SQUARE bk   = pb[0];
	SQUARE pawn = pb[1];

	assert (A2 <= pawn && pawn < A8);

	if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
		pawn = flipWE (pawn);
		wk   = flipWE (wk);		
		bk   = flipWE (bk);		
		wa   = flipWE (wa);
		wa2  = flipWE (wa2);
	}

	pawn = flipNS(pawn);
	pslice = wsq_to_pidx24 (pawn);

	aa_combo = (index_t)aaidx [wa] [wa2];

	if (IDX_is_empty(aa_combo)) {
		*out = NOINDEX;
		return FALSE;
	}	

	*out = pslice * (index_t)BLOCK_A + (index_t)wk * (index_t)BLOCK_B  + (index_t)bk * (index_t)BLOCK_C + aa_combo;

	assert (*out >= 0);

	return TRUE;
}

/********************** end KAA/KP ************************************/

/**********************  KPP/KP ************************************/
/*
index_t 	pp48_idx[48][48];
sq_t		pp48_sq_x[MAX_PP48_INDEX];
sq_t		pp48_sq_y[MAX_PP48_INDEX]; 
*/
static bool_t 	test_kppkp (void);
static bool_t 	kppkp_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
static void		kppkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb);

static sq_t map24_b   (sq_t s);
static sq_t unmap24_b (index_t i);

static index_t
init_pp48_idx (void)
/* modifies pp48_idx[][], pp48_sq_x[], pp48_sq_y[] */
{
	enum  {MAX_I = 48, MAX_J = 48};
	SQUARE i, j;
	index_t idx = 0;
	SQUARE a, b;

	/* default is noindex */
	for (i = 0; i < MAX_I; i++) {
		for (j = 0; j < MAX_J; j++) {
			IDX_set_empty (pp48_idx [i][j]);
		}
	}
		
	for (idx = 0; idx < MAX_PP48_INDEX; idx++) {
		pp48_sq_x [idx] = NOSQUARE;	
		pp48_sq_y [idx] = NOSQUARE;			
	}		
		
	idx = 0;
	for (a = H7; a >= A2; a--) {

		for (b = a - 1; b >= A2; b--) {

			i = flipWE( flipNS (a) ) - 8;
			j = flipWE( flipNS (b) ) - 8;
			
			if (IDX_is_empty(pp48_idx [i] [j])) {

				pp48_idx  [i][j]= idx; 	assert (idx < MAX_PP48_INDEX);
				pp48_idx  [j][i]= idx;
				pp48_sq_x [idx] = i; 	assert (i < MAX_I);
				pp48_sq_y [idx] = j; 	assert (j < MAX_J);		
				idx++;
			}
		}	
	}
	assert (idx == MAX_PP48_INDEX);
	return idx;
}



static bool_t
test_kppkp (void)
{

	enum 		{MAXPC = 16+1};
	char 		str[] = "kppkp";
	SQUARE 		a, b, c, d, e;
	SQUARE 		pw[MAXPC], pb[MAXPC];
	SQUARE 		px[MAXPC], py[MAXPC];	

	index_t		i, j;
	bool_t 		err = FALSE;

	printf ("%8s ", str);

	for (a = 0; a < 64; a++) {
		for (b = 0; b < 64; b++) {
		for (c = 0; c < 64; c++) {
		for (d = 0; d < 64; d++) {
		for (e = 0; e < 64; e++) {

			if (c <= H1 || c >= A8)
				continue;
			if (b <= H1 || b >= A8)
				continue;
			if (d <= H1 || d >= A8)
				continue;
			
			pw[0] = a;
			pw[1] = b;	
			pw[2] = c;
			pw[3] = NOSQUARE;
		
			pb[0] = e;
			pb[1] = d;
			pb[2] = NOSQUARE;
	
			if (kppkp_pctoindex (pw, pb, &i)) {
							kppkp_indextopc (i, px, py);		
							kppkp_pctoindex (px, py, &j);
							if (i != j) {
								err = TRUE;
							}
							assert (i == j);	
			}
	
		}
		}
		}
		}

        if ((a&1)==0) {
            printf(".");
            fflush(stdout);
        }
	}

	if (err)		
		printf ("> %s NOT passed\n", str);	
	else
		printf ("> %s PASSED\n", str);	
	return !err;
}


static void
kppkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	/*---------------------------------------------------------*
		inverse work to make sure that the following is valid
		index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d; 
	*----------------------------------------------------------*/

	enum  {BLOCK_A = MAX_PP48_INDEX*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; 
	index_t a, b, c, d, r;
	SQUARE m, n;
	
	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;
	b  = r / BLOCK_B;
	r -= b * BLOCK_B;	
	c  = r / BLOCK_C;
	r -= c * BLOCK_C;	
	d  = r;
	
	m = pp48_sq_x [b];
	n = pp48_sq_y [b];
	
	pw[0] = (SQUARE)c;
	pw[1] = flipWE(flipNS(m+8));
	pw[2] = flipWE(flipNS(n+8));
	pw[3] = NOSQUARE;

	pb[0] = (SQUARE)d;	
	pb[1] = (SQUARE)unmap24_b (a);
	pb[2] = NOSQUARE;	


	assert (A2 <= pw[1] && pw[1] < A8);
	assert (A2 <= pw[2] && pw[2] < A8);
	assert (A2 <= pb[1] && pb[1] < A8);
	assert (kppkp_pctoindex (pw, pb, &a) && a == i);

	return;
}


static bool_t 
kppkp_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
{
	enum  {BLOCK_A = MAX_PP48_INDEX*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; 
	index_t pp48_slice;	
	
	SQUARE wk     = pw[0];
	SQUARE pawn_a = pw[1];
	SQUARE pawn_b = pw[2];
	SQUARE bk     = pb[0];
	SQUARE pawn_c = pb[1];	
	SQUARE i, j, k;

	assert (A2 <= pawn_a && pawn_a < A8);
	assert (A2 <= pawn_b && pawn_b < A8);
	assert (A2 <= pawn_c && pawn_c < A8);

	if ((pawn_c & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
		wk     = flipWE (wk);		
		pawn_a = flipWE (pawn_a);
		pawn_b = flipWE (pawn_b);
		bk     = flipWE (bk);		
		pawn_c = flipWE (pawn_c);	
	}
 
	i = flipWE( flipNS (pawn_a) ) - 8;
	j = flipWE( flipNS (pawn_b) ) - 8;
	k = map24_b (pawn_c); /* black pawn, so low indexes mean more advanced 0 == A2 */

	pp48_slice = pp48_idx [i] [j];

	if (IDX_is_empty(pp48_slice)) {
		*out = NOINDEX;
		return FALSE;
	}

	assert (pp48_slice < MAX_PP48_INDEX );
	
	*out = (index_t)k * (index_t)BLOCK_A + pp48_slice * (index_t)BLOCK_B + (index_t)wk * (index_t)BLOCK_C  + (index_t)bk;

	return TRUE;
}

static sq_t
map24_b (sq_t s)
{
	s -= 8;
	return ((s&3)+s)>>1;
}

static sq_t
unmap24_b (index_t i)
{
	return (sq_t) ((i&(4+8+16)) + i + 8);
}

/********************** end KPP/KP ************************************/

/**********************  KPPP/K ************************************/

static const sq_t itosq[48] = {
	H7,G7,F7,E7,
	H6,G6,F6,E6,
	H5,G5,F5,E5,
	H4,G4,F4,E4,
	H3,G3,F3,E3,
	H2,G2,F2,E2,
	D7,C7,B7,A7,
	D6,C6,B6,A6,
	D5,C5,B5,A5,
	D4,C4,B4,A4,
	D3,C3,B3,A3,
	D2,C2,B2,A2
};

static bool_t 	test_kpppk (void);
static bool_t 	kpppk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
static void		kpppk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);

static index_t
init_ppp48_idx (void)
/* modifies ppp48_idx[][], ppp48_sq_x[], ppp48_sq_y[], ppp48_sq_z[] */
{
	enum  {MAX_I = 48, MAX_J = 48, MAX_K = 48};
	SQUARE i, j, k;
	index_t idx = 0;
	SQUARE a, b, c;
	int x, y, z;

	/* default is noindex */
	for (i = 0; i < MAX_I; i++) {
		for (j = 0; j < MAX_J; j++) {
			for (k = 0; k < MAX_K; k++) {
				IDX_set_empty(ppp48_idx [i][j][k]);
			}
		}
	}
		
	for (idx = 0; idx < MAX_PPP48_INDEX; idx++) {
		ppp48_sq_x [idx] = (uint8_t)NOSQUARE;	
		ppp48_sq_y [idx] = (uint8_t)NOSQUARE;	
		ppp48_sq_z [idx] = (uint8_t)NOSQUARE;		
	}		

	idx = 0;
	for (x = 0; x < 48; x++) {
		for (y = x+1; y < 48; y++) {
			for (z = y+1; z < 48; z++) {

				a = itosq [x];
				b = itosq [y];
				c = itosq [z];
		
				if (!in_queenside(b) || !in_queenside(c))			
						continue;

				i = a - 8;
				j = b - 8;
				k = c - 8;
				
				if (IDX_is_empty(ppp48_idx [i] [j] [k])) {

					ppp48_idx  [i][j][k] = idx; 	
					ppp48_idx  [i][k][j] = idx;
					ppp48_idx  [j][i][k] = idx;
					ppp48_idx  [j][k][i] = idx;
					ppp48_idx  [k][i][j] = idx;
					ppp48_idx  [k][j][i] = idx;
					ppp48_sq_x [idx] = (uint8_t) i; 	assert (i < MAX_I);
					ppp48_sq_y [idx] = (uint8_t) j; 	assert (j < MAX_J);		
					ppp48_sq_z [idx] = (uint8_t) k; 	assert (k < MAX_K);	
					idx++;
				}
			}
		}	
	}

/*	assert (idx == MAX_PPP48_INDEX);*/
	return idx;
}

static bool_t
test_kpppk (void)
{

	enum 		{MAXPC = 16+1};
	char 		str[] = "kpppk";
	SQUARE 		a, b, c, d, e;
	SQUARE 		pw[MAXPC], pb[MAXPC];
	SQUARE 		px[MAXPC], py[MAXPC];	

	index_t		i, j;
	bool_t 		err = FALSE;

	printf ("%8s ", str);

	for (a = 0; a < 64; a++) {
		for (b = 0; b < 64; b++) {
		for (c = 0; c < 64; c++) {
		for (d = 0; d < 64; d++) {
		for (e = 0; e < 64; e++) {

			if (c <= H1 || c >= A8)
				continue;
			if (b <= H1 || b >= A8)
				continue;
			if (d <= H1 || d >= A8)
				continue;
			
			pw[0] = a;
			pw[1] = b;	
			pw[2] = c;
			pw[3] = d;
			pw[4] = NOSQUARE;
		
			pb[0] = e;
			pb[1] = NOSQUARE;
	
			if (kpppk_pctoindex (pw, pb, &i)) {
							kpppk_indextopc (i, px, py);		
							kpppk_pctoindex (px, py, &j);
							if (i != j) {
								err = TRUE;
							}
							assert (i == j);	
			}
	
		}
		}
		}
		}

        if ((a&1)==0) {
            printf(".");
            fflush(stdout);
        }
	}

	if (err)		
		printf ("> %s NOT passed\n", str);	
	else
		printf ("> %s PASSED\n", str);	
	return !err;
}


static void
kpppk_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	/*---------------------------------------------------------*
		inverse work to make sure that the following is valid
		index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d; 
	*----------------------------------------------------------*/

	enum  {BLOCK_A = 64*64, BLOCK_B = 64}; 
	index_t a, b, c, r;
	SQUARE m, n, o;
	
	r  = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;
	b  = r / BLOCK_B;
	r -= b * BLOCK_B;	
	c  = r;
	
	m = ppp48_sq_x [a];
	n = ppp48_sq_y [a];
	o = ppp48_sq_z [a];

	
	pw[0] = (SQUARE)b;
	pw[1] = m + 8;
	pw[2] = n + 8;
	pw[3] = o + 8;
	pw[4] = NOSQUARE;

	pb[0] = (SQUARE)c;	
	pb[1] = NOSQUARE;	


	assert (A2 <= pw[1] && pw[1] < A8);
	assert (A2 <= pw[2] && pw[2] < A8);
	assert (A2 <= pw[3] && pw[3] < A8);
	assert (kpppk_pctoindex (pw, pb, &a) && a == i);

	return;
}


static bool_t 
kpppk_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
{
	enum  {BLOCK_A = 64*64, BLOCK_B = 64}; 
	index_t ppp48_slice;	
	
	SQUARE wk     = pw[0];
	SQUARE pawn_a = pw[1];
	SQUARE pawn_b = pw[2];
	SQUARE pawn_c = pw[3];	

	SQUARE bk     = pb[0];

	SQUARE i, j, k;

	assert (A2 <= pawn_a && pawn_a < A8);
	assert (A2 <= pawn_b && pawn_b < A8);
	assert (A2 <= pawn_c && pawn_c < A8);

	i = pawn_a - 8;
	j = pawn_b - 8;
	k = pawn_c - 8;

	ppp48_slice = ppp48_idx [i] [j] [k];

	if (IDX_is_empty(ppp48_slice)) { 
		wk     = flipWE (wk);		
		pawn_a = flipWE (pawn_a);
		pawn_b = flipWE (pawn_b);
		pawn_c = flipWE (pawn_c);
		bk     = flipWE (bk);		
	}

	i = pawn_a - 8;
	j = pawn_b - 8;
	k = pawn_c - 8;

	ppp48_slice = ppp48_idx [i] [j] [k];
 
	if (IDX_is_empty(ppp48_slice)) {
		*out = NOINDEX;
		return FALSE;
	}

	assert (ppp48_slice < MAX_PPP48_INDEX );
	
	*out = (index_t)ppp48_slice * BLOCK_A + (index_t)wk * BLOCK_B  + (index_t)bk;

	return TRUE;
}


/********************** end KPPP/K ************************************/


static bool_t 
kpkp_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
{
	enum  {BLOCK_A = 64*64, BLOCK_B = 64}; 	
	SQUARE pp_slice;	
	SQUARE anchor, loosen;
	
	SQUARE wk     = pw[0];
	SQUARE bk     = pb[0];
	SQUARE pawn_a = pw[1];
	SQUARE pawn_b = pb[1];

	SQUARE m, n;

	#ifdef DEBUG
	if (!(A2 <= pawn_a && pawn_a < A8)) {
		printf ("\n\nsquare of pawn_a: %s\n", Square_str[pawn_a]);
		printf(" wk %s\n p1 %s\n p2 %s\n bk %s\n"
			, Square_str[wk]
			, Square_str[pawn_a]
			, Square_str[pawn_b]
			, Square_str[bk]
			);
	}
	#endif

	assert (A2 <= pawn_a && pawn_a < A8);
	assert (A2 <= pawn_b && pawn_b < A8);
	assert (pw[2] == NOSQUARE && pb[2] == NOSQUARE);

	/*pp_putanchorfirst (pawn_a, pawn_b, &anchor, &loosen);*/
	anchor = pawn_a;
	loosen = pawn_b;

	if ((anchor & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
		anchor = flipWE (anchor);
		loosen = flipWE (loosen);
		wk     = flipWE (wk);		
		bk     = flipWE (bk);		
	}
 
	m = (SQUARE)wsq_to_pidx24 (anchor);
	n = loosen - 8;

	pp_slice = m * 48 + n; 

	if (IDX_is_empty(pp_slice)) {
		*out = NOINDEX;
		return FALSE;
	}

	assert (pp_slice < MAX_PpINDEX );
	
	*out = (index_t) (pp_slice * BLOCK_A + wk * BLOCK_B  + bk);

	return TRUE;
}


static void
kpkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
{
	/*---------------------------------------------------------*
		inverse work to make sure that the following is valid
		index = a * BLOCK_A + b * BLOCK_B + c; 
	*----------------------------------------------------------*/
	enum  {B11100  = 7u << 2};
	enum  {BLOCK_A = 64*64, BLOCK_B = 64}; 
	enum  {block_m = 48};
	index_t a, b, c, r;
	index_t m, n;
	SQUARE sq_m, sq_n;
	
	r = i;
	a  = r / BLOCK_A;
	r -= a * BLOCK_A;
	b  = r / BLOCK_B;
	r -= b * BLOCK_B;	
	c  = r;
	
	/* unpack a, which is pslice, into m and n */
	r = a;
	m  = r / block_m;
	r -= m * block_m;
	n  = r ;

	sq_m  = pidx24_to_wsq (m);
	sq_n  = (SQUARE)n + 8;
	
	pw[0] = (SQUARE)b;
	pb[0] = (SQUARE)c;	
	pw[1] = sq_m;
	pb[1] = sq_n;
	pw[2] = NOSQUARE;
	pb[2] = NOSQUARE;	
	
	assert (A2 <= pw[1] && pw[1] < A8);
	assert (A2 <= pb[1] && pb[1] < A8);

	return;
}


{28,"knkp", MAX_kakp, 24,kakp_indextopc, kakp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
	/**/
{29,"kqpk", MAX_kapk, 24,kapk_indextopc, kapk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{30,"krpk", MAX_kapk, 24,kapk_indextopc, kapk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{31,"kbpk", MAX_kapk, 24,kapk_indextopc, kapk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{32,"knpk", MAX_kapk, 24,kapk_indextopc, kapk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
	/**/	
{33,"kppk", MAX_kppk, MAX_PPINDEX ,kppk_indextopc, kppk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
	/**/
{34,"kpkp", MAX_kpkp, MAX_PpINDEX ,kpkp_indextopc, kpkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
	/**/
	/**/
	/* 5 pieces */
{ 35,"kqqqk", MAX_kaaak, 1, kaaak_indextopc, kaaak_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 36,"kqqrk", MAX_kaabk, 1, kaabk_indextopc, kaabk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 37,"kqqbk", MAX_kaabk, 1, kaabk_indextopc, kaabk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 38,"kqqnk", MAX_kaabk, 1, kaabk_indextopc, kaabk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 39,"kqrrk", MAX_kabbk, 1, kabbk_indextopc, kabbk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 40,"kqrbk", MAX_kabck, 1, kabck_indextopc, kabck_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 41,"kqrnk", MAX_kabck, 1, kabck_indextopc, kabck_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 42,"kqbbk", MAX_kabbk, 1, kabbk_indextopc, kabbk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 43,"kqbnk", MAX_kabck, 1, kabck_indextopc, kabck_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 44,"kqnnk", MAX_kabbk, 1, kabbk_indextopc, kabbk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 45,"krrrk", MAX_kaaak, 1, kaaak_indextopc, kaaak_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 46,"krrbk", MAX_kaabk, 1, kaabk_indextopc, kaabk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 47,"krrnk", MAX_kaabk, 1, kaabk_indextopc, kaabk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 48,"krbbk", MAX_kabbk, 1, kabbk_indextopc, kabbk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 49,"krbnk", MAX_kabck, 1, kabck_indextopc, kabck_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 50,"krnnk", MAX_kabbk, 1, kabbk_indextopc, kabbk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 51,"kbbbk", MAX_kaaak, 1, kaaak_indextopc, kaaak_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 52,"kbbnk", MAX_kaabk, 1, kaabk_indextopc, kaabk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 53,"kbnnk", MAX_kabbk, 1, kabbk_indextopc, kabbk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 54,"knnnk", MAX_kaaak, 1, kaaak_indextopc, kaaak_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 55,"kqqkq", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 56,"kqqkr", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 57,"kqqkb", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 58,"kqqkn", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 59,"kqrkq", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 60,"kqrkr", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 61,"kqrkb", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 62,"kqrkn", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 63,"kqbkq", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 64,"kqbkr", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 65,"kqbkb", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 66,"kqbkn", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 67,"kqnkq", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 68,"kqnkr", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 69,"kqnkb", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 70,"kqnkn", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 71,"krrkq", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 72,"krrkr", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 73,"krrkb", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 74,"krrkn", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 75,"krbkq", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 76,"krbkr", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 77,"krbkb", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 78,"krbkn", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 79,"krnkq", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 80,"krnkr", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 81,"krnkb", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 82,"krnkn", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 83,"kbbkq", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 84,"kbbkr", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 85,"kbbkb", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 86,"kbbkn", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 87,"kbnkq", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 88,"kbnkr", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 89,"kbnkb", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 90,"kbnkn", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 91,"knnkq", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 92,"knnkr", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 93,"knnkb", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 94,"knnkn", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },

{ 95,"kqqpk", MAX_kaapk, 24, kaapk_indextopc, kaapk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 96,"kqrpk", MAX_kabpk, 24, kabpk_indextopc, kabpk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 97,"kqbpk", MAX_kabpk, 24, kabpk_indextopc, kabpk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 98,"kqnpk", MAX_kabpk, 24, kabpk_indextopc, kabpk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{ 99,"krrpk", MAX_kaapk, 24, kaapk_indextopc, kaapk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{100,"krbpk", MAX_kabpk, 24, kabpk_indextopc, kabpk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{101,"krnpk", MAX_kabpk, 24, kabpk_indextopc, kabpk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{102,"kbbpk", MAX_kaapk, 24, kaapk_indextopc, kaapk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{103,"kbnpk", MAX_kabpk, 24, kabpk_indextopc, kabpk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{104,"knnpk", MAX_kaapk, 24, kaapk_indextopc, kaapk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },

{105,"kqppk", MAX_kappk, MAX_PPINDEX, kappk_indextopc, kappk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{106,"krppk", MAX_kappk, MAX_PPINDEX, kappk_indextopc, kappk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{107,"kbppk", MAX_kappk, MAX_PPINDEX, kappk_indextopc, kappk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{108,"knppk", MAX_kappk, MAX_PPINDEX, kappk_indextopc, kappk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },

{109,"kqpkq", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{110,"kqpkr", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{111,"kqpkb", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{112,"kqpkn", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{113,"krpkq", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{114,"krpkr", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{115,"krpkb", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{116,"krpkn", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{117,"kbpkq", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{118,"kbpkr", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{119,"kbpkb", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{120,"kbpkn", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{121,"knpkq", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{122,"knpkr", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{123,"knpkb", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{124,"knpkn", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },

{125,"kppkq", MAX_kppka, MAX_PPINDEX, kppka_indextopc, kppka_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{126,"kppkr", MAX_kppka, MAX_PPINDEX, kppka_indextopc, kppka_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{127,"kppkb", MAX_kppka, MAX_PPINDEX, kppka_indextopc, kppka_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{128,"kppkn", MAX_kppka, MAX_PPINDEX, kppka_indextopc, kppka_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },

{129,"kqqkp", MAX_kaakp, 24, kaakp_indextopc, kaakp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{130,"kqrkp", MAX_kabkp, 24, kabkp_indextopc, kabkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{131,"kqbkp", MAX_kabkp, 24, kabkp_indextopc, kabkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{132,"kqnkp", MAX_kabkp, 24, kabkp_indextopc, kabkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{133,"krrkp", MAX_kaakp, 24, kaakp_indextopc, kaakp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{134,"krbkp", MAX_kabkp, 24, kabkp_indextopc, kabkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{135,"krnkp", MAX_kabkp, 24, kabkp_indextopc, kabkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{136,"kbbkp", MAX_kaakp, 24, kaakp_indextopc, kaakp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{137,"kbnkp", MAX_kabkp, 24, kabkp_indextopc, kabkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{138,"knnkp", MAX_kaakp, 24, kaakp_indextopc, kaakp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },

{139,"kqpkp", MAX_kapkp, MAX_PpINDEX, kapkp_indextopc, kapkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{140,"krpkp", MAX_kapkp, MAX_PpINDEX, kapkp_indextopc, kapkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{141,"kbpkp", MAX_kapkp, MAX_PpINDEX, kapkp_indextopc, kapkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{142,"knpkp", MAX_kapkp, MAX_PpINDEX, kapkp_indextopc, kapkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },

{143,"kppkp", MAX_kppkp, 24*MAX_PP48_INDEX, kppkp_indextopc, kppkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
{144,"kpppk", MAX_kpppk, MAX_PPP48_INDEX, kpppk_indextopc, kpppk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },

{MAX_EGKEYS, NULL,  0,        1, NULL,           NULL,           NULL,   NULL   ,NULL ,0 ,0}

};



/****************************************************************************\
 *
 *
 *								INDEXING ZONE
 *
 *
 ****************************************************************************/

static void
init_indexing (int verbosity)
{
	index_t a,b,c,d,e,f;

	init_flipt ();

	a = init_kkidx     () ;	
	b = init_ppidx     () ;	
	c = init_aaidx     () ;
	d = init_aaa       () ;
	e = init_pp48_idx  () ;
	f = init_ppp48_idx () ;

	if (verbosity) {
		printf ("\nGTB supporting tables, Initialization\n");
		printf ("  Max    kk idx: %8d\n", (int)a );	
		printf ("  Max    pp idx: %8d\n", (int)b );	
		printf ("  Max    aa idx: %8d\n", (int)c );
		printf ("  Max   aaa idx: %8d\n", (int)d );
		printf ("  Max  pp48 idx: %8d\n", (int)e );
		printf ("  Max ppp48 idx: %8d\n", (int)f );
	}

	if (!reach_was_initialized())
		reach_init();

	/* testing used only in development stage */

#ifdef _MSC_VER
#pragma warning(disable:4127)
#endif

	if (0) {
		list_index ();
		printf ("\nTEST indexing functions\n");

		test_kaakb ();
		test_kaabk ();
		test_kaaak ();
		test_kabbk ();
	
		test_kapkb ();
		test_kabkp ();
	
		test_kppka ();

		test_kapkp ();
		test_kabpk();
		test_kaapk ();
	
		test_kappk ();	
		test_kaakp ();
		test_kppk ();
	 	test_kppkp ();
	 	test_kpppk ();
	}	

#ifdef _MSC_VER
#pragma warning(default:4127)
#endif

	return;
}


static index_t
init_kkidx (void)
/* modifies kkidx[][], wksq[], bksq[] */
{
	index_t idx;
	SQUARE x, y, i, j;
	
	/* default is noindex */
	for (x = 0; x < 64; x++) {
		for (y = 0; y < 64; y++) {
			IDX_set_empty(kkidx [x][y]);
		}
	}

	idx = 0;
	for (x = 0; x < 64; x++) {
		for (y = 0; y < 64; y++) {
		
			/* is x,y illegal? continue */
			if (possible_attack (x, y, wK) || x == y)
				continue;
		
			/* normalize */
			/*i <-- x; j <-- y */
			norm_kkindex (x, y, &i, &j);
		
			if (IDX_is_empty(kkidx [i][j])) { /* still empty */
				kkidx [i][j] = idx;
				kkidx [x][y] = idx;
				bksq [idx] = i;
				wksq [idx] = j;			
				idx++;
			}
		}
	}
	
	assert (idx == MAX_KKINDEX);

	return idx;
}


static index_t
init_aaidx (void)
/* modifies aabase[], aaidx[][] */
{
	index_t idx;
	SQUARE x, y;
	
	/* default is noindex */
	for (x = 0; x < 64; x++) {
		for (y = 0; y < 64; y++) {
			IDX_set_empty(aaidx [x][y]);
		}
	}

	for (idx = 0; idx < MAX_AAINDEX; idx++)
		aabase [idx] = 0;

	idx = 0;
	for (x = 0; x < 64; x++) {
		for (y = x + 1; y < 64; y++) {

			assert (idx == (int)((y - x) + x * (127-x)/2 - 1) );

			if (IDX_is_empty(aaidx [x][y])) { /* still empty */
				aaidx [x] [y] = idx; 
				aaidx [y] [x] = idx;
				aabase [idx] = (unsigned char) x;
				idx++;
			} else {
				assert (aaidx [x] [y] == idx);
				assert (aabase [idx] == x);
			}


		}
	}
	
	assert (idx == MAX_AAINDEX);

	return idx;
}


static index_t
init_ppidx (void)
/* modifies ppidx[][], pp_hi24[], pp_lo48[] */
{
	index_t i, j;
	index_t idx = 0;
	SQUARE a, b;

	/* default is noindex */
	for (i = 0; i < 24; i++) {
		for (j = 0; j < 48; j++) {
			IDX_set_empty(ppidx [i][j]);
		}
	}
		
	for (idx = 0; idx < MAX_PPINDEX; idx++) {
		IDX_set_empty(pp_hi24 [idx]);
		IDX_set_empty(pp_lo48 [idx]);		
	}		
		
	idx = 0;
	for (a = H7; a >= A2; a--) {

		if ((a & 07) < 4) /* square in the queen side */
			continue;

		for (b = a - 1; b >= A2; b--) {
			
			SQUARE anchor, loosen;
	
			pp_putanchorfirst (a, b, &anchor, &loosen);
			
			if ((anchor & 07) > 3) { /* square in the king side */
				anchor = flipWE(anchor);
				loosen = flipWE(loosen);				
			}
			
			i = wsq_to_pidx24 (anchor);
			j = wsq_to_pidx48 (loosen);
			
			if (IDX_is_empty(ppidx [i] [j])) {

                ppidx [i] [j] = idx;
                assert (idx < MAX_PPINDEX);
                pp_hi24 [idx] = i;
                assert (i < 24);
                pp_lo48 [idx] =	j;
                assert (j < 48);
				idx++;
			}
			
		}	
	}
	assert (idx == MAX_PPINDEX);
	return idx;
}

static void
init_flipt (void)
{
	unsigned int i, j;
	for (i = 0; i < 64; i++) {
		for (j = 0; j < 64; j++) {
			flipt [i] [j] = flip_type (i, j);
		}		
	}
}

/*--- NORMALIZE -------*/

static void
norm_kkindex (SQUARE x, SQUARE y, /*@out@*/ SQUARE *pi, /*@out@*/ SQUARE *pj)
{
	unsigned int rowx, rowy, colx, coly;
	
	assert (x < 64);
	assert (y < 64);
	
	if (getcol(x) > 3) { 
		x = flipWE (x); /* x = x ^ 07  */
		y = flipWE (y);		
	}
	if (getrow(x) > 3)  { 
		x = flipNS (x); /* x = x ^ 070  */
		y = flipNS (y);		
	}	
	rowx = getrow(x);
	colx = getcol(x);
	if ( rowx > colx ) {
		x = flipNW_SE (x); /* x = ((x&7)<<3) | (x>>3) */
		y = flipNW_SE (y);			
	}
	rowy = getrow(y);
	coly = getcol(y);	
	if ( rowx == colx && rowy > coly) {
		x = flipNW_SE (x);
		y = flipNW_SE (y);			
	}	
	
	*pi = x;
	*pj = y;
}

static unsigned int
flip_type (SQUARE x, SQUARE y)
{
	unsigned int rowx, rowy, colx, coly;
	unsigned int ret = 0;
	
	assert (x < 64);
	assert (y < 64);
	
	
	if (getcol(x) > 3) { 
		x = flipWE (x); /* x = x ^ 07  */
		y = flipWE (y);		
		ret |= 1;
	}
	if (getrow(x) > 3)  { 
		x = flipNS (x); /* x = x ^ 070  */
		y = flipNS (y);		
		ret |= 2;		
	}	
	rowx = getrow(x);
	colx = getcol(x);
	if ( rowx > colx ) {
		x = flipNW_SE (x); /* x = ((x&7)<<3) | (x>>3) */
		y = flipNW_SE (y);	
		ret |= 4;				
	}
	rowy = getrow(y);
	coly = getcol(y);	
	if ( rowx == colx && rowy > coly) {
		x = flipNW_SE (x);
		y = flipNW_SE (y);	
		ret |= 4;					
	}	
	return ret;
}


static void
pp_putanchorfirst (SQUARE a, SQUARE b, /*@out@*/ SQUARE *out_anchor, /*@out@*/ SQUARE *out_loosen)
{
	unsigned int anchor, loosen;
			
	unsigned int row_b, row_a;
	row_b = b & 070;
	row_a = a & 070;
			
	/* default */
	anchor = a;
	loosen = b;
	if (row_b > row_a) {
		anchor = b;
		loosen = a;
	} 
	else
	if (row_b == row_a) {
		unsigned int x, col, inv, hi_a, hi_b;
		x = a;
		col = x & 07;
		inv = col ^ 07;
		x = (1u<<col) | (1u<<inv);
		x &= (x-1);	
		hi_a = x;
		
		x = b;
		col = x & 07;
		inv = col ^ 07;
		x = (1u<<col) | (1u<<inv);
		x &= (x-1);	
		hi_b = x;			
				
		if (hi_b > hi_a) {
			anchor = b;
			loosen = a;					
		}

		if (hi_b < hi_a) {
			anchor = a;
			loosen = b;					
		}

		if (hi_b == hi_a) {
			if (a < b) {
				anchor = a;
				loosen = b;	
			} else {
				anchor = b;
				loosen = a;	
			}				
		}
	}

	*out_anchor = anchor;
	*out_loosen = loosen;
	return;
}


static index_t
wsq_to_pidx24 (SQUARE pawn)
{
	unsigned int idx24;
	SQUARE sq = pawn;

	/* input can be only queen side, pawn valid */
	assert (A2 <= pawn && pawn < A8);
	assert ((pawn & 07) < 4);

	sq ^= 070; /* flipNS*/
	sq -= 8;   /* down one row*/
	idx24 = (sq+(sq&3)) >> 1; 
	assert (idx24 < 24);
	return (index_t) idx24;
}

static index_t
wsq_to_pidx48 (SQUARE pawn)
{
	unsigned int idx48;
	SQUARE sq = pawn;

	/* input can be both queen or king side, pawn valid square  */
	assert (A2 <= pawn && pawn < A8);

	sq ^= 070; /* flipNS*/
	sq -= 8;   /* down one row*/
	idx48 = sq;
	assert (idx48 < 48);
	return (index_t)idx48;
}

static SQUARE
pidx24_to_wsq (index_t a)
{
	enum  {B11100  = 7u << 2};
	unsigned int x = (unsigned int) a; 	/* x is pslice */
	assert (a < 24);

	x += x & B11100; /* get upper part and double it */
	x += 8;          /* add extra row  */
	x ^= 070;        /* flip NS */
	return (SQUARE) x;
}

static SQUARE
pidx48_to_wsq (index_t a)
{
	unsigned int x;
	assert (a < 48);
	/* x is pslice */
	x = (unsigned int)a;
	x += 8;          /* add extra row  */
	x ^= 070;        /* flip NS */
	return x;
}



/****************************************************************************\
|
|
|						PATH MANAGEMENT ZONE
|
|
\****************************************************************************/

#define MAXPATHLEN tb_MAXPATHLEN
#define MAX_GTBPATHS 10

static int  			Gtbpath_end_index = 0;
static const char **	Gtbpath = NULL;

/*---------------- EXTERNAL PATH MANAGEMENT --------------------------------*/

extern const char *tbpaths_getmain (void) {	return Gtbpath[0];}

extern const char **
tbpaths_init(void)
{
	const char **newps;
	newps = (const char **) malloc (sizeof (char *));
	if (newps != NULL) {
		newps[0] = NULL;
	}
	return newps;
}

static const char **
tbpaths_add_single(const char **ps, const char *newpath)
{
	size_t counter;
	const char **newps;
	size_t i, psize;
	char *ppath;

	if (NULL == ps)
		return NULL;

	psize = strlen(newpath) + 1;
	ppath = (char *) malloc (psize * sizeof (char));
	if (NULL == ppath)
		return ps; /* failed to incorporate a new path */
	for (i = 0; i < psize; i++) ppath[i] = newpath[i];

	for (counter = 0; ps[counter] != NULL; counter++)
		; 

	/* cast to deal with const poisoning */
	newps =	(const char **) realloc ((char **)ps, sizeof(char *) * (counter+2));
	if (newps != NULL) {
		newps [counter] = ppath;
		newps [counter+1] = NULL;
	}
	return newps;
}


extern const char **
tbpaths_add(const char **ps, const char *newpath)
{
	size_t i, psize;
	char *mpath;

	if (NULL == ps)
		return NULL;

	psize = strlen(newpath) + 1;
	mpath = (char *) malloc (psize * sizeof (char));
	if (NULL == mpath) {
		return ps; /* failed to incorporate a new path */
	}
	for (i = 0; i < psize; i++) mpath[i] = newpath[i];	

	for (i = 0; i < psize; i++) {
		if(';' == mpath[i])
			mpath[i] = '\0';	
	}

	for (i = 0;;) {
		while (i < psize && mpath[i] == '\0') i++;
		if (i >= psize) break;
		ps = tbpaths_add_single (ps, &mpath[i]);
		while (i < psize && mpath[i] != '\0') i++;
	}

	free(mpath);
	return ps;
}


extern const char **
tbpaths_done(const char **ps)
{
	int counter;
	void *q;	

	if (ps != NULL) {
		for (counter = 0; ps[counter] != NULL; counter++) {
			/* cast to deal with const poisoning */
			void *p = (void *) ps[counter];
			free(p);		
		} 	
		/* cast to deal with const poisoning */
		q = (void *) ps;
		free(q);
	}
	return NULL;
}

/*---------------- PATH INITIALIZATION ROUTINES ----------------------------*/

static void path_system_reset(void) {Gtbpath_end_index = 0;}

static bool_t
path_system_init (const char **path)
{
	size_t i;
	size_t sz;
	const char *x;
	bool_t ok = TRUE;
	path_system_reset();

	if (path == NULL) {
		return FALSE;
	}

	/* calculate needed size for Gtbpath */
	i = 0;
	do {
		x = path[i++];
	} while (x != NULL);
	sz = i; /* sz includes the NULL */


	Gtbpath = (const char **) malloc (sz * sizeof(char *));

	if (Gtbpath) {
		
		ok = TRUE;
		/* point to the same strings provided */
		Gtbpath_end_index = 0;
		for (i = 0; i < sz; i++) {
			Gtbpath[i] = path[i];
			Gtbpath_end_index++;
		}

	} else {
		ok = FALSE;
	}
	return ok;

}

static void
path_system_done (void)
{
	/* before we free Gtbpath, we have to deal with the
	"const poisoning" and cast it. free() does not accept
	const pointers */
	char **	p = (char **) Gtbpath;	
	/* clean up */
	if (p != NULL)
		free(p);
	return;
}


static void
removepiece (SQUARE *ys, SQ_CONTENT *yp, int j)
{
    int k;
	for (k = j; ys[k] != NOSQUARE; k++) {
		ys[k] = ys[k+1];
		yp[k] = yp[k+1];
	}
}

/* 
|
|	mySHARED by probe and build 
|
\*----------------------------------------------------*/


#ifdef _MSC_VER
/* to silence warning for sprintf usage */
#pragma warning(default:4996)
#endif

mySHARED void
sortlists (SQUARE *ws, SQ_CONTENT *wp)
{
	int i, j;
	SQUARE ts;
	SQ_CONTENT tp;
	/* input is sorted */
	for (i = 0; wp[i] != NOPIECE; i++) {
		for (j = (i+1); wp[j] != NOPIECE; j++) {	
			if (wp[j] > wp[i]) {
				tp = wp[i]; wp[i] = wp[j]; wp[j] = tp;		
				ts = ws[i]; ws[i] = ws[j]; ws[j] = ts;
			}			
		}	
	}
}

mySHARED void
list_sq_copy (const SQUARE *a, SQUARE *b)
{
	while (NOSQUARE != (*b++ = *a++))
		;
}

mySHARED void
list_pc_copy (const SQ_CONTENT *a, SQ_CONTENT *b)
{
	while (NOPIECE != (*b++ = *a++))
		;
}
